<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>ktz.</title><description>Podcaster. Musician. Photographer. Tailscalar.</description><link>https://blog.ktz.me/</link><language>en-us</language><image><url>https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w256h256/2021/09/2773080.png</url><title>ktz.</title><link>https://blog.ktz.me/</link></image><generator>Astro</generator><lastBuildDate>Sun, 12 Jul 2026 03:59:29 GMT</lastBuildDate><atom:link href="https://blog.ktz.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title>How I Made My 10-Year-Old Nvidia Shield Feel Brand New</title><link>https://blog.ktz.me/nvidia-shield-adb-projectivy-performance-refresh/</link><guid isPermaLink="false">local-158b6d90-111e-4042-8031-914ceed87e79</guid><description>Cleaning up the Nvidia Shield: the exact ADB commands from the video, how to verify them, and how to roll everything back.</description><pubDate>Sun, 12 Jul 2026 03:59:29 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/07/nvidia-shield-adb-projectivy-performance-refresh/nvidia-shield-youtube-thumbnail.webp&quot; alt=&quot;Nvidia Shield TV and remote beside the words Still the GOAT&quot;&gt;&lt;p&gt;The original Nvidia Shield TV has had an extraordinary run, but ten years of apps, updates, launchers, and background services had left mine feeling sluggish.&lt;/p&gt;
&lt;p&gt;I used Codex and Android Debug Bridge (ADB) to inspect it over my local network. The biggest issue was simple: Projectivy Launcher was visible, but Android TV Home was still registered as the real home app and continued running behind it.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-embed-card&quot;&gt;&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/6b1nBC-lkk0&quot; title=&quot;How I Made My 10-Year-Old Nvidia Shield Feel Brand New&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;&lt;/figure&gt;
&lt;p&gt;The steps below make Projectivy the actual home app, disable the unused stock launcher components, shorten Android’s animations, compile Projectivy for faster startup, and verify that everything survives a reboot.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;These commands are specific to my Shield TV setup. ADB provides administrator-like access, so review every command before running it. This is a responsiveness tune-up, not a hardware upgrade.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;before-you-start&quot;&gt;Before you start&lt;/h2&gt;
&lt;p&gt;Install and configure &lt;a href=&quot;https://github.com/spocky/miproja1&quot;&gt;Projectivy Launcher&lt;/a&gt; before disabling the stock launcher. You will also need Google’s &lt;a href=&quot;https://developer.android.com/tools/adb&quot;&gt;ADB platform tools&lt;/a&gt;. On macOS:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;brew&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; android-platform-tools&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enable network debugging on the Shield:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;Settings &amp;gt; Device Preferences &amp;gt; About&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Build&lt;/code&gt; seven times.&lt;/li&gt;
&lt;li&gt;Return to &lt;code&gt;Device Preferences &amp;gt; Developer options&lt;/code&gt; and enable &lt;code&gt;Network debugging&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the Shield’s IP address under &lt;code&gt;Network &amp;amp; Internet&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/07/nvidia-shield-adb-projectivy-performance-refresh/developer-options.webp&quot; alt=&quot;Developer mode enabled on the Nvidia Shield&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/07/nvidia-shield-adb-projectivy-performance-refresh/developer-options.webp 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/07/nvidia-shield-adb-projectivy-performance-refresh/developer-options.webp 1000w&quot; sizes=&quot;(min-width: 720px) 720px, 90vw&quot;&gt;&lt;/p&gt;
&lt;p&gt;Connect from your computer, substituting the Shield’s address:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; connect&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; YOUR_SHIELD_IP:5555&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; devices&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Accept the authorization prompt on the TV. The device should appear as &lt;code&gt;device&lt;/code&gt; rather than &lt;code&gt;unauthorized&lt;/code&gt; or &lt;code&gt;offline&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Before changing anything, record the current launcher and animation settings:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; resolve-activity&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --brief&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  -a&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; android.intent.action.MAIN&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  -c&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; android.intent.category.HOME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; window_animation_scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; transition_animation_scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; animator_duration_scale&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;apply-the-changes&quot;&gt;Apply the changes&lt;/h2&gt;
&lt;p&gt;Run these commands one at a time:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; set-home-activity&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  com.spocky.projengmenu/.ui.home.MainActivity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; disable-user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.google.android.tvlauncher&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; disable-user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.google.android.tvrecommendations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; disable-user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.netflix.ninja&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; window_animation_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; transition_animation_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; animator_duration_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 0.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; compile&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -m&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; speed&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -f&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.spocky.projengmenu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; am&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; kill-all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What they do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;set-home-activity&lt;/code&gt; makes Projectivy Android’s real home app instead of leaving it layered over Android TV Home.&lt;/li&gt;
&lt;li&gt;The two Google &lt;code&gt;disable-user&lt;/code&gt; commands disable the stock launcher and recommendations for user 0. They do not remove the packages, so the change is reversible.&lt;/li&gt;
&lt;li&gt;Disabling &lt;code&gt;com.netflix.ninja&lt;/code&gt; is optional. It neutralized the dedicated Netflix remote button in my setup, but also disables the Netflix app. Skip it if you use Netflix.&lt;/li&gt;
&lt;li&gt;The three animation settings halve transition times. This changes perceived responsiveness rather than processor performance.&lt;/li&gt;
&lt;li&gt;The final commands compile Projectivy in speed mode, stop disposable background processes, and reboot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I deliberately left Chromecast, Google Play Services, Bluetooth, voice control, media providers, and Nvidia system services alone.&lt;/p&gt;
&lt;h2 id=&quot;verify-the-result&quot;&gt;Verify the result&lt;/h2&gt;
&lt;p&gt;Reconnect after the reboot and check the active home app, animation values, and relevant processes:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; connect&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; YOUR_SHIELD_IP:5555&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; resolve-activity&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --brief&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  -a&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; android.intent.action.MAIN&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  -c&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; android.intent.category.HOME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; window_animation_scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; transition_animation_scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; animator_duration_scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; ps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -A&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -E&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &apos;projengmenu|tvlauncher|tvrecommendations|netflix&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The home resolver should return Projectivy, each animation value should be &lt;code&gt;0.5&lt;/code&gt;, and the disabled packages should not have running processes. Test the home button, voice input, casting, Bluetooth remote, and your usual apps.&lt;/p&gt;
&lt;h2 id=&quot;roll-everything-back&quot;&gt;Roll everything back&lt;/h2&gt;
&lt;p&gt;These commands re-enable the disabled apps, restore normal animation timing, and select Android TV Home again:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; enable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.netflix.ninja&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; enable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.google.android.tvlauncher&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; pm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; enable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; com.google.android.tvrecommendations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; window_animation_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; transition_animation_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; settings&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; global&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; animator_duration_scale&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; set-home-activity&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  com.google.android.tvlauncher/.MainActivity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If that stock component name changes in a future Shield release, enable the packages, reboot, and choose Android TV Home from the on-screen home-app picker instead of guessing another activity name.&lt;/p&gt;
&lt;p&gt;A Shield update may re-enable system packages, so recheck the resolved home app afterward. Once you are finished, turn off &lt;code&gt;Network debugging&lt;/code&gt; to be on the safe side. Happy Shielding.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/07/nvidia-shield-adb-projectivy-performance-refresh/nvidia-shield-youtube-thumbnail.webp" medium="image"/><category>technical</category><category>hardware</category><category>codex</category><category>ai</category></item><item><title>Faking disks to look real with QEMU and Proxmox</title><link>https://blog.ktz.me/faking-disks-to-look-real-with-qemu-and-proxmox/</link><guid isPermaLink="false">6a24aebf363d4c000160276c</guid><description>Proxmox can give virtual disks realistic identities, but `serial=` alone is not enough for `inxi -xD` to make things feel real in a test environment.</description><pubDate>Sat, 06 Jun 2026 23:46:24 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/06/Generated-image-1.png&quot; alt=&quot;Faking disks to look real with QEMU and Proxmox&quot;&gt;&lt;p&gt;Whilst prepping for &lt;a href=&quot;http://perfectmediaserver.com/?ref=blog.ktz.me&quot;&gt;Perfect Media Server&lt;/a&gt; Part 3, I needed to conduct some testing with a Proxmox VM and make fake QEMU disks attached via SCSI look real to &lt;code&gt;inxi -xD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The problem was that &lt;code&gt;inxi&lt;/code&gt; kept showing generic &lt;code&gt;QEMU HARDDISK&lt;/code&gt;. Fine, but not what I wanted when filming a video about how to identify physical disks and map them to your &lt;code&gt;fstab&lt;/code&gt; file. I had hoped I could make it feel a bit more real in the video without having to drag a ton of old physical disks out of storage.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;shellsession&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;root@proxtest:~&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;# inxi -xD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;Drives:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  Local Storage: total: 240 GiB lvm-free: 16 GiB used: 5.71 GiB (2.4%)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  ID-1: /dev/sda vendor: QEMU model: HARDDISK size: 10 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  ID-2: /dev/sdb vendor: QEMU model: HARDDISK size: 8 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  ID-3: /dev/sdc vendor: QEMU model: HARDDISK size: 5 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  ID-4: /dev/sdd vendor: QEMU model: HARDDISK size: 7 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  ID-5: /dev/sde vendor: QEMU model: HARDDISK size: 10 GiB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, setting the &lt;code&gt;serial=&lt;/code&gt; parameter had no effect. Which led me to do a deepdive on the fields that Proxmox SCSI disks support:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;product&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;serial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;wwn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The useful ones for &lt;code&gt;inxi -xD&lt;/code&gt; are &lt;code&gt;vendor&lt;/code&gt; and &lt;code&gt;product&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is one example:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;qm&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;  --scsi0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; local-lvm:vm-1000-disk-2,discard=on,iothread=1,product=WD10EZEX-D10A,serial=SNAP1000D10A,size=10G,vendor=WDC,wwn=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;0x5000100001001000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I did that for each fake disk. Then after a full VM stop and start, &lt;code&gt;inxi -xD&lt;/code&gt; showed me what I wanted. Pretty convincing at first glance, wouldn’t you say? Perfect for my needs tonight.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ID-1: /dev/sda vendor: Western Digital model: WD10EZEX-D10A size: 10 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ID-2: /dev/sdb vendor: HGST (Hitachi) model: HDN7280D08 size: 8 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ID-3: /dev/sdc vendor: Crucial model: CT500MX500D05 size: 5 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ID-4: /dev/sdd vendor: Seagate model: ST7000VN-D07 size: 7 GiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ID-5: /dev/sde vendor: Western Digital model: WD10PURX-P10 size: 10 GiB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A couple of small gotchas, you can only set the values to a max:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vendor  = max 8 bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;product = max 16 bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;serial  = max 20 bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;wwn     = 0x plus 16 hex digits&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, &lt;code&gt;vendor=WDC&lt;/code&gt; shows up as &lt;code&gt;Western Digital&lt;/code&gt; in &lt;code&gt;inxi&lt;/code&gt; because&amp;nbsp;it&amp;nbsp;normalizes some short hardware vendor codes into friendly names. &lt;code&gt;WDC&lt;/code&gt;&amp;nbsp;is the common vendor string for Western Digital disks. Linux sees the SCSI vendor as&amp;nbsp;&lt;code&gt;WDC&lt;/code&gt;, but&amp;nbsp;&lt;code&gt;inxi&lt;/code&gt;&amp;nbsp;maps that to&amp;nbsp;Western Digital&amp;nbsp;for display.&lt;/p&gt;
&lt;p&gt;Hope you found this little tip useful.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/06/Generated-image-1.png" medium="image"/><category>technical</category></item><item><title>Control a Mitsubishi mini-split with ESPHome and Home Assistant for $10</title><link>https://blog.ktz.me/control-a-mitsubishi-mini-split-with-esphome-and-home-assistant-for-10/</link><guid isPermaLink="false">67ec066a5cf9d20001462bb1</guid><description>Fully open hardware and software to control a proprietary appliance? Yes please.</description><pubDate>Wed, 27 May 2026 01:49:50 GMT</pubDate><content:encoded>&lt;p&gt;I recently had a Mitsubishi mini-split air conditioner installed as part of an attic conversion project. The device was, according to the installer, only controllable via the IR remote. And that just won’t do.&lt;/p&gt;
&lt;p&gt;So in today’s post I’m going to detail how I used an ESP32 running ESPHome to achieve bi-directional control of the Mitsubishi units using the CN105 control port on the mainboard of the head unit.&lt;/p&gt;
&lt;h2 id=&quot;what-to-expect&quot;&gt;What to expect&lt;/h2&gt;
&lt;p&gt;These units are not cheap. So please only do this if you are comfortable. I am not a lawyer so please apply your own risk disclaimers for damage to property and yourself in case of screw ups. Turn off the power to the units before opening anything up, go slow and take your time. It’s not a difficult install and should be an easy afternoon project for most DIY’ers.&lt;/p&gt;
&lt;p&gt;The hardware install can be completed in under 10 minutes. The first time will likely take a bit longer as the plastic housings of the units can be a bit fiddly to free from the clips. I cover this is more detail in the video.&lt;/p&gt;
&lt;p&gt;The software side might trip a few folks up the first time as there are a few moving parts. I assume for the purposes of this post that you have a functional Home Assistant installation, and a functional ESPHome installation atop it.&lt;/p&gt;
&lt;h2 id=&quot;parts&quot;&gt;Parts&lt;/h2&gt;
&lt;p&gt;To complete this project you will need:&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Item&lt;/th&gt;&lt;th&gt;Price&lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://amzn.to/4jhNZ5d?ref=blog.ktz.me&quot;&gt;ESP32&lt;/a&gt;&lt;/td&gt;&lt;td&gt;$5&lt;/td&gt;&lt;td&gt;The brains of the operation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://amzn.to/42mQUDT?ref=blog.ktz.me&quot;&gt;Connector PAP-05V-S&lt;/a&gt;&lt;/td&gt;&lt;td&gt;$7&lt;/td&gt;&lt;td&gt;Connect ESP32 to CN105 port&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that I have linked to multi-packs of ESP32s and of the connectors too, you might be able to find these things cheaper elsewhere but regardless it’s still a low cost project.&lt;/p&gt;
&lt;p&gt;Also note that these links are affiliate links to support my work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;unit-disassembly&quot;&gt;Unit disassembly&lt;/h2&gt;
&lt;p&gt;The unit I have is the &lt;code&gt;MSZ-GS09NA&lt;/code&gt;, though I have found that the process seems broadly the same across the units in NA I have come across, your mileage may vary.&lt;/p&gt;
&lt;p&gt;Begin by turning off power at the breaker, and removing the vanes of the unit. There are two plastic tabs that slide and lock the vanes in position.&lt;/p&gt;
&lt;p&gt;With the vanes removed, look for two small plastic screw covers and remove them and their associated screws.&lt;/p&gt;
&lt;p&gt;The centre of the unit will have a small screwless retaining clip, give it a sharp tug in the middle towards you and free the housing pulling it straight off the front of the unit. It does not pivot (like the filter housings do).&lt;/p&gt;
&lt;p&gt;Once the housing is removed look for the grey mainboard cover on the right of the unit and locate the red coloured CN105 port. We’ll come back to this later.&lt;/p&gt;
&lt;h2 id=&quot;esp-configuration&quot;&gt;ESP configuration&lt;/h2&gt;
&lt;p&gt;This process is not yet fully written up as I got distracted but the code is below so reach out if you get stuck&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-bookmark-card&quot;&gt;&lt;a class=&quot;kg-bookmark-container&quot; href=&quot;https://gist.github.com/ironicbadger/eebd34e6392219dcff98e0d1ffdfa52a?ref=blog.ktz.me&quot;&gt;&lt;div class=&quot;kg-bookmark-content&quot;&gt;&lt;div class=&quot;kg-bookmark-title&quot;&gt;esphome-mitsubishi.yaml&lt;/div&gt;&lt;div class=&quot;kg-bookmark-description&quot;&gt;GitHub Gist: instantly share code, notes, and snippets.&lt;/div&gt;&lt;div class=&quot;kg-bookmark-metadata&quot;&gt;&lt;img class=&quot;kg-bookmark-icon&quot; src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/icon/pinned-octocat-093da3e6fa40-2.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;span class=&quot;kg-bookmark-author&quot;&gt;Gist&lt;/span&gt;&lt;span class=&quot;kg-bookmark-publisher&quot;&gt;262588213843476&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;kg-bookmark-thumbnail&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/thumbnail/gist-og-image-54fd7dc0713e.png&quot; alt=&quot;&quot; onerror=&quot;this.style.display = &apos;none&apos;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;kg-card kg-image-card&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/06/image.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;968&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2025/06/image.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2025/06/image.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;figure class=&quot;kg-card kg-image-card&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/06/image-1.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1444&quot; height=&quot;968&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2025/06/image-1.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2025/06/image-1.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator></item><item><title>The Enshittification of Plex 💩</title><link>https://blog.ktz.me/the-enshittification-of-plex/</link><guid isPermaLink="false">6a131f1102e4350001a456f8</guid><description>&quot;But lifetime passers are grandfathered in&quot; you might say, &quot;so why should I care?&quot;.</description><pubDate>Sun, 24 May 2026 20:44:44 GMT</pubDate><content:encoded>&lt;img src=&quot;https://images.unsplash.com/photo-1695509120014-83adf2b2d6e3?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDMwfHx2aWRlbyUyMHJlbnRhbCUyMHN0b3JlfGVufDB8fHx8MTc3OTYzODE2N3ww&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=2000&quot; alt=&quot;The Enshittification of Plex 💩&quot;&gt;&lt;p&gt;Perhaps you heard the news this week that Plex is raising the cost of a lifetime pass from $250 to $750? Perhaps you’ve become numb to the general enshittification of the Plex Media Server software?&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-embed-card&quot;&gt;&lt;iframe width=&quot;200&quot; height=&quot;113&quot; src=&quot;https://www.youtube.com/embed/s9ELRrIXVmQ?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;What Happened to Plex? The 15 Year Timeline&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;&lt;/figure&gt;
&lt;p&gt;Today, I’m going to break down everything that’s happened over the last decade that got us to this point. I’ll aim to be as factually accurate as possible. But I’m now at the point with Plex where I’m done. I’m out. It has been obvious for years that there is only one end result here and with the news of the massive price hike recently I’m fairly certain we are watching the final stages of collapse.&lt;/p&gt;
&lt;p&gt;“But lifetime passers are grandfathered in” you might say, “so why should I care?”. That is true, they are. But Plex has to exist for their authentication services, live TV EPG services, and many more aspects of the Plex experience to work at all. So if Plex the company goes away, then so will everything else around it regardless of whether you have a lifetime pass, as I do, or not.&lt;/p&gt;
&lt;p&gt;I’m switching to Jellyfin for good, and I hope you will too.&lt;/p&gt;
&lt;h2 id=&quot;what-is-plex&quot;&gt;What is Plex?&lt;/h2&gt;
&lt;p&gt;It’s a “bring your own files”, self-hosted version of a media streaming platform like a Netflix or Spotify. But you run the service on your hardware, streaming your files, using your electricity, hardware, and so forth.&lt;/p&gt;
&lt;p&gt;Plex began as a fork of XBMC, originally as a Mac OS X port of XBMC. At the time it was known as OSXBMC and was the creation of &lt;a href=&quot;https://www.crunchbase.com/person/elan-feingold?ref=blog.ktz.me&quot;&gt;Elan Feingold&lt;/a&gt;. In May 2008 the Plex name was adopted after the XBMC codebase was forked. Kodi’s own wiki - Kodi is the newer modern name for the XBMC project - notes that newer Plex clients were later rewritten and are no longer based on the forked code.&lt;/p&gt;
&lt;p&gt;License is a particularly messy area of Plex’s history. XBMC was GPL-based, so early Plex inherited open-source obligations, but Plex evolved into a commerical product with significant closed-source/proprietary parts. Some Plex client code has remained &lt;a href=&quot;https://support.plex.tv/articles/204096476-license-information/?ref=blog.ktz.me&quot;&gt;open&lt;/a&gt; for compliance reasons, but the core Plex Media Server code is not open-source.&lt;/p&gt;
&lt;h2 id=&quot;what-is-jellyfin&quot;&gt;What is Jellyfin?&lt;/h2&gt;
&lt;p&gt;To answer this we must introduce &lt;a href=&quot;https://emby.media/?ref=blog.ktz.me&quot;&gt;Emby&lt;/a&gt;. Emby &lt;a href=&quot;https://emby.media/introducing-emby.html?ref=blog.ktz.me&quot;&gt;came from&lt;/a&gt; a separate lineage of media software known as Media Browser in March 2015. Jellyfin is a fork of Emby. The split here occurred in 2018 from Emby v3.5.2 after Emby moved toward a proprietary/closed-source model.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://jellyfin.org/?ref=blog.ktz.me&quot;&gt;Jellyfin&lt;/a&gt; is the free-software continuation and alternative to both Emby and Plex.&lt;/p&gt;
&lt;h2 id=&quot;a-timeline-of-events&quot;&gt;A timeline of events&lt;/h2&gt;
&lt;p&gt;The idea here is give you a picture of the notably things that have happened in the Plex universe over the last decade or so. You can see quite clearly around 2019+ how the company has been flailing and looking for a purpose since The Verge’s article in July 2019.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/blog/part-2-introducing-plexpass/?ref=blog.ktz.me&quot;&gt;August 2012&lt;/a&gt; - PlexPass launches
&lt;ul&gt;
&lt;li&gt;Plex framed PlexPass as a supporter / early-access program&lt;/li&gt;
&lt;li&gt;Early access, private forums, premium feature testing, and discounts were part of the pitch&lt;/li&gt;
&lt;li&gt;Launch price was $3.99/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/blog/announcing-the-new-plexpass-feature/?ref=blog.ktz.me&quot;&gt;November 2012&lt;/a&gt; - PlexSync becomes an early premium feature
&lt;ul&gt;
&lt;li&gt;PlexSync let users reformat and load media onto mobile devices for offline viewing&lt;/li&gt;
&lt;li&gt;Announced as a PlexPass feature&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20160816132608/https://www.plex.tv/blog/upcoming-price-increase-new-plex-pass-subscriptions/&quot;&gt;September 2014&lt;/a&gt; - Plex Pass price hike
&lt;ul&gt;
&lt;li&gt;Plex announced new pricing effective Sept 2014
&lt;ul&gt;
&lt;li&gt;Monthly increased from $3.99 -&amp;gt; $4.99&lt;/li&gt;
&lt;li&gt;Annual increased from $29.99 -&amp;gt; $39.99&lt;/li&gt;
&lt;li&gt;Lifetime increase from $74.99 -&amp;gt; $149.99&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/en-gb/blog/introducing-plex-home/?ref=blog.ktz.me&quot;&gt;November 2014&lt;/a&gt; - Plex Home / parental-control tiering
&lt;ul&gt;
&lt;li&gt;Plex introduced Plex Home, managed users, and finer access controls&lt;/li&gt;
&lt;li&gt;Some multiuser features became free&lt;/li&gt;
&lt;li&gt;More advanced Home / sharing controls stayed Plex Pass&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://haveibeenpwned.com/Breach/Plex?ref=blog.ktz.me&quot;&gt;July 2015&lt;/a&gt; - &lt;a href=&quot;https://web.archive.org/web/20160708094738/https://www.plex.tv/blog/security-notice-forum-user-password-resets/&quot;&gt;Forum security breach&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Plex’s forum was hacked.&lt;/li&gt;
&lt;li&gt;HaveIBeenPwnd.net listed 327,000+ exposed accounts including emails, IPs, usernames, and weakly implemented salted password hashes.&lt;/li&gt;
&lt;li&gt;Plex reset users passwords&lt;/li&gt;
&lt;li&gt;Reports noted a ransom demand&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.techspot.com/news/66183-plex-adds-dvr-feature-over-air-broadcasts.html?ref=blog.ktz.me&quot;&gt;September 2016&lt;/a&gt; - DVR beta added to Plex Pass
&lt;ul&gt;
&lt;li&gt;Plex DVR launched in beta for Plex Pass subscribers&lt;/li&gt;
&lt;li&gt;Initially tied to HDHomeRun tuners and guide data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forums.plex.tv/t/plex-beta-1-7-1-3856/193235?ref=blog.ktz.me&quot;&gt;December 2016&lt;/a&gt; - Hardware transcoding preview
&lt;ul&gt;
&lt;li&gt;Plex Media Server 1.4.0 added a Hardware Transcoding Preview&lt;/li&gt;
&lt;li&gt;It was introduced as a Plex Pass feature for Windows, macOS, and Linux&lt;/li&gt;
&lt;li&gt;Early support included Intel graphics caveats&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.plex.tv/articles/115002178853-using-hardware-accelerated-streaming/?ref=blog.ktz.me&quot;&gt;Plex’s current docs&lt;/a&gt; still list hardware-accelerated streaming as premium, while ordinary software transcoding remains free
&lt;ul&gt;
&lt;li&gt;exceptions include NVIDIA SHIELD and WD My Cloud Pro PR2100 / PR4100 servers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/de/blog/well-do-it-live/?ref=blog.ktz.me&quot;&gt;June-August 2017&lt;/a&gt; - Live TV / DVR solidifies as Plex Pass
&lt;ul&gt;
&lt;li&gt;Plex added Live TV and later expanded time shifting / DVR support&lt;/li&gt;
&lt;li&gt;Live TV / DVR required Plex Pass plus supported tuner / antenna hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://techcrunch.com/2017/08/21/plex-changes-its-new-privacy-policy-after-backlash-clarified-its-not-trying-to-see-whats-in-your-library/?ref=blog.ktz.me&quot;&gt;August 2017&lt;/a&gt; - Privacy policy changes and backlash
&lt;ul&gt;
&lt;li&gt;A proposed policy removed users’ ability to opt out of some data collection, prompting fears about library tracking&lt;/li&gt;
&lt;li&gt;Plex revised the policy in response and restored opt-out controls&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/plexlabs/introducing-plexamp-9493a658847a?ref=blog.ktz.me&quot;&gt;December 2017&lt;/a&gt; - Plexamp launches
&lt;ul&gt;
&lt;li&gt;Plex Labs unveiled Plexamp as its first project&lt;/li&gt;
&lt;li&gt;A Winamp-inspired desktop music player for Plex music libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20251209132452/https://forums.plex.tv/t/discontinuation-of-plugins-watch-later-recommended-and-cloud-sync/312312&quot;&gt;October 2018&lt;/a&gt; - Plex Cloud and feature retirements
&lt;ul&gt;
&lt;li&gt;Plex retires Watch Later, Recommended, Cloud Sync and plugins&lt;/li&gt;
&lt;li&gt;Plex shutdown their hosted Plex Cloud service after reliability / cost problems&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/blog/turning-plex-music-up-to-eleventy/?ref=blog.ktz.me&quot;&gt;Nov 2018&lt;/a&gt; - Plex adds TIDAL integration
&lt;ul&gt;
&lt;li&gt;This added streaming music, TIDAL-powered discovery, universal playlists/search, and library augmentation alongside personal music collections&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20260520081748/https://www.theverge.com/2019/7/23/20697751/piracy-plex-netflix-hulu-streaming-wars&quot;&gt;July 2019&lt;/a&gt; - The Verge very publicly highlights Plex’s piracy problem
&lt;ul&gt;
&lt;li&gt;A Verge feature highlighted Plex’s role in private shared libraries&lt;/li&gt;
&lt;li&gt;Plex is framed as enabling “unofficial piracy streaming clubs”&lt;/li&gt;
&lt;li&gt;Emphasizes the piracy problem that Plex has (ed: and always will have!)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20260128101801/https://techcrunch.com/2019/12/04/plex-launches-a-free-ad-supported-streaming-service-in-over-200-countries/&quot;&gt;Dec 2019&lt;/a&gt; - Ad-supported streaming launches
&lt;ul&gt;
&lt;li&gt;Plex launched free, ad-supported movies and TV in 200+ countries,&lt;/li&gt;
&lt;li&gt;This marked a major pivot beyond personal media libraries into studio-backed streaming&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20260511034244/https://www.netscout.com/blog/asert/plex-media-ssdp-pmssdp-reflectionamplification-ddos-attack&quot;&gt;Feb 2020&lt;/a&gt; - Plex servers used for DDoS amplication
&lt;ul&gt;
&lt;li&gt;Researchers found exposed Plex Media Server instances being abused for PMSSDP reflection/amplification DDoS attacks&lt;/li&gt;
&lt;li&gt;Plex said unusual network exposure was required and shipped a hotfix&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://techcrunch.com/2020/04/16/media-software-maker-plex-launches-new-subscriber-only-apps-for-music-and-server-management/?ref=blog.ktz.me&quot;&gt;Apr 2020&lt;/a&gt; - Plexamp 3.0 relaunch
&lt;ul&gt;
&lt;li&gt;Plexamp was rewritten/relaunched across desktop and mobile as a Plex Pass app&lt;/li&gt;
&lt;li&gt;coverage notes its search/recent plays included servers, podcasts, and TIDAL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/en-au/blog/go-ahead-and-skip-that-intro/?ref=blog.ktz.me&quot;&gt;May 2020&lt;/a&gt; - Skip Intro added
&lt;ul&gt;
&lt;li&gt;Plex launched Skip Intro as a new Plex Pass feature for TV libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20200630022418/https://forums.plex.tv/t/security-regarding-cve-2020-5741/586819&quot;&gt;May 2020&lt;/a&gt; - CVE-2020-5741
&lt;ul&gt;
&lt;li&gt;Flaw where an attacker with admin account access could abuse Camera Upload to execute malicious code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20251213182957/https://www.plex.tv/blog/the-one-where-plex-announces-free-streaming-live-tv/&quot;&gt;July 2020&lt;/a&gt; - Free Live TV expands Plex’s ad business
&lt;ul&gt;
&lt;li&gt;Plex launched free Live TV in 220+ countries with 80+ channels, further broadening its shift toward ad-supported streaming&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20251216150726/https://www.plex.tv/blog/game-on-a-plex-blog-story/&quot;&gt;Jan 2021 - Mar 2022&lt;/a&gt; - Plex Arcade gets the “killed by Google” treatment
&lt;ul&gt;
&lt;li&gt;Plex launched a retro-game streaming subscription with Atari/Parsec&lt;/li&gt;
&lt;li&gt;Then announced Plex Arcade would shut down on Mar. 31, 2022&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.globenewswire.com/de/news-release/2021/04/14/2210024/34264/en/Streaming-Media-Platform-Plex-Raises-50-Million-in-Growth-Equity-to-Become-the-One-Stop-Shop-for-Movies-and-TV.html?ref=blog.ktz.me&quot;&gt;April 2021&lt;/a&gt; - Plex &lt;a href=&quot;https://web.archive.org/web/20260524145722/https://www.globenewswire.com/de/news-release/2021/04/14/2210024/34264/en/Streaming-Media-Platform-Plex-Raises-50-Million-in-Growth-Equity-to-Become-the-One-Stop-Shop-for-Movies-and-TV.html&quot;&gt;raises $50m&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Plex announced a growth equity investment round from existing investor Intercap&lt;/li&gt;
&lt;li&gt;Only about $15M was new capital&lt;/li&gt;
&lt;li&gt;The rest was used to buy shares/options from employees and shareholders&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forums.plex.tv/t/security-regarding-cve-2021-42835/761510?ref=blog.ktz.me&quot;&gt;Dec 2021&lt;/a&gt; - CVE-2021-42835
&lt;ul&gt;
&lt;li&gt;Plex disclosed a Windows local privilege-escalation flaw affecting PMS before 1.25.0&lt;/li&gt;
&lt;li&gt;Exploitation required local/physical access and was fixed in 1.25.0.5282+&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20260523013553/https://techcrunch.com/2022/04/05/huge-plex-update-adds-a-universal-watchlist-cross-service-search-and-new-discovery-features/&quot;&gt;April 2022&lt;/a&gt; - Universal Watchlist and cross-service search
&lt;ul&gt;
&lt;li&gt;Plex launched Discover (&lt;a href=&quot;https://www.reddit.com/r/PleX/comments/u1uvqf/how_do_i_turn_off_discovery/?ref=blog.ktz.me&quot;&gt;to a &lt;em&gt;mixed&lt;/em&gt; response&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Launched cross-service search&lt;/li&gt;
&lt;li&gt;And a universal watchlist to help users find content across streaming services&lt;/li&gt;
&lt;li&gt;Presumably aimed at become a “one stop shop” for all your streaming needs?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20250919134743/https://forums.plex.tv/t/important-notice-of-a-potential-data-breach-24th-of-august-2022/806518&quot;&gt;August 2022&lt;/a&gt; - Account database breach
&lt;ul&gt;
&lt;li&gt;Another breach this time involving suspicious database activity&lt;/li&gt;
&lt;li&gt;A third party accessed emails, usernames, and encrypted/bcrypt-hashed passwords&lt;/li&gt;
&lt;li&gt;Plex forced account password resets and said payment data was not stored&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/en-gb/blog/let-the-next-episode-roll/?ref=blog.ktz.me&quot;&gt;Feb 2023&lt;/a&gt; - Skip Credits added
&lt;ul&gt;
&lt;li&gt;Skip Credits became available for Plex Pass holders on personal libraries&lt;/li&gt;
&lt;li&gt;Plex’s own free streaming catalog also got the feature&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20260519095025/https://thehackernews.com/2023/03/lastpass-hack-engineers-failure-to.html&quot;&gt;Mar 2023&lt;/a&gt; - LastPass breach linked to unpatched Plex on an employees computer
&lt;ul&gt;
&lt;li&gt;Reports said attackers exploited an old Plex flaw on a LastPass engineer’s home computer&lt;/li&gt;
&lt;li&gt;CISA added CVE-2020-5741 to its known-exploited catalog&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plex.tv/blog/free-bird-plexamp-spreads-its-wings-for-every-music-lover/?ref=blog.ktz.me&quot;&gt;Jul 2023&lt;/a&gt; - Plexamp becomes free
&lt;ul&gt;
&lt;li&gt;Plex made core Plexamp free for all users&lt;/li&gt;
&lt;li&gt;Advanced features such as downloads, Sonic Sage, and some Guest DJ features behind Plex Pass&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20230915165531/https://torrentfreak.com/plex-will-block-media-servers-at-prevalent-hosting-company-230915/&quot;&gt;Sept 2023&lt;/a&gt; - Hetzner ban hammer on Plex servers
&lt;ul&gt;
&lt;li&gt;Plex warned users that servers at a hosting provider widely identified as Hetzner would be blocked over large-scale ToS violations&lt;/li&gt;
&lt;li&gt;Sparked &lt;em&gt;yet another&lt;/em&gt; anti-piracy and legitimisation debate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.theverge.com/2023/11/27/23978451/plex-users-have-some-valid-concerns-about-its-new-activity-sharing-feature?ref=blog.ktz.me&quot;&gt;November 2023&lt;/a&gt; - Discovery Together privacy controversy
&lt;ul&gt;
&lt;li&gt;“Your week in review” emails leak user watch habits&lt;/li&gt;
&lt;li&gt;This triggering Reddit/forum outrage over opt-out social sharing and concerns that personal-server watch history was being exposed without clear consent&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://techcrunch.com/2024/02/07/streamer-plex-launches-its-long-promised-movie-rentals-store/?ref=blog.ktz.me&quot;&gt;Feb 2024&lt;/a&gt; - Movie rentals launch
&lt;ul&gt;
&lt;li&gt;Plex launched a movie-rental store with 1,000+ titles&lt;/li&gt;
&lt;li&gt;Coverage criticized limits such as U.S.-focused availability, 1080p/5.1 quality, no 4K HDR, and no downloads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.bloomberglaw.com/litigation/plex-user-advances-suit-over-sharing-of-viewing-info-with-meta?ref=blog.ktz.me&quot;&gt;April 2024 - Jun 2025&lt;/a&gt; - VPPA / Meta lawsuit
&lt;ul&gt;
&lt;li&gt;Plex faced a proposed class action alleging it shared viewing histories with Meta&lt;/li&gt;
&lt;li&gt;The suit advanced in Mar. 2025 but was voluntarily dismissed in Jun. 2025&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forums.plex.tv/t/tidal-integration-with-plex-ending-october-28-2024/885728?ref=blog.ktz.me&quot;&gt;October 2024&lt;/a&gt; - TIDAL integration removed
&lt;ul&gt;
&lt;li&gt;This meant Plexamp would no longer connect to TIDAL&lt;/li&gt;
&lt;li&gt;Plex-billed TIDAL subs stopped&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20250319151649/https://www.plex.tv/blog/important-2025-plex-updates/&quot;&gt;Apr-Nov 2025&lt;/a&gt; - Price hikes and remote paywalls go up
&lt;ul&gt;
&lt;li&gt;Plex Pass prices went up for the first time in a decade
&lt;ul&gt;
&lt;li&gt;Monthly - $4.99 -&amp;gt; $6.99&lt;/li&gt;
&lt;li&gt;Annual - $39.99 -&amp;gt; $69.99&lt;/li&gt;
&lt;li&gt;Lifetime - $149.99 -&amp;gt; $249.99&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Remote personal-playback became paid&lt;/li&gt;
&lt;li&gt;Enforcement began later in 2025&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=FcorAYtHHhQ&amp;amp;ref=blog.ktz.me&quot;&gt;Alex and Robbie purchase soapboxes&lt;/a&gt; and make use of them&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.bleepingcomputer.com/news/security/plex-warns-users-to-patch-security-vulnerability-immediately/?ref=blog.ktz.me&quot;&gt;Aug 2025&lt;/a&gt; - CVE-2025-34158
&lt;ul&gt;
&lt;li&gt;NVD described the flaw as exposing server-owner credentials in PMS 1.41.7.x–1.42.0.x before 1.42.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20250908213946/https://forums.plex.tv/t/important-notice-of-security-incident/930523&quot;&gt;Sep 2025&lt;/a&gt; - A security incident
&lt;ul&gt;
&lt;li&gt;An unauthorized third party accessed emails, usernames, securely hashed passwords, and authentication data from one database&lt;/li&gt;
&lt;li&gt;users were told to reset passwords or SSO sessions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arstechnica.com/gadgets/2026/05/plexs-200-lifetime-pass-price-hike-tries-forcing-users-to-another-subscription/?ref=blog.ktz.me&quot;&gt;May 2026&lt;/a&gt; - Plex hikes the prices by 200% for lifetime
&lt;ul&gt;
&lt;li&gt;Lifetime increases from $249.99 -&amp;gt; $749.99&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.androidauthority.com/plex-remote-watch-pass-price-increase-3663060?ref=blog.ktz.me&quot;&gt;Jun 2026&lt;/a&gt; - Remote Watch Pass price increase scheduled
&lt;ul&gt;
&lt;li&gt;Official plan pages show Remote Watch Pass intro pricing ending June 1&lt;/li&gt;
&lt;li&gt;Prices rise from $1.99/$19.99 to $2.99/$29.99 monthly/yearly&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://alternativeto.net/news/2026/5/plex-to-raise-lifetime-plex-pass-price-to-749-99-on-july-1-2026/?ref=blog.ktz.me&quot;&gt;July 2026&lt;/a&gt; - Lifetime Plex Pass jumps again
&lt;ul&gt;
&lt;li&gt;Scheduled for July 1, 2026&lt;/li&gt;
&lt;li&gt;Lifetime Plex Pass increases from $249.99 -&amp;gt; $749.99&lt;/li&gt;
&lt;li&gt;Monthly and annual prices stay unchanged&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;my-conclusions-from-this-timeline&quot;&gt;My conclusions from this timeline&lt;/h2&gt;
&lt;p&gt;Over the past decade we have watched Plex flail around looking for a viable business model. What started as a paid supporter tier for early access and genuinely useful personal-media features has slowly become a ratchet. More investor pressure, ad-supported streaming, attempts to become a discovery layer for other services, privacy controversies, price hikes, pieces of the personal-media experience moved behind some kind of recurring payment.&lt;/p&gt;
&lt;p&gt;The company has never fully escaped the piracy shadow, but it has also spent years drifting away from the people who used Plex for the legitimate and simple reason that it was the best way to stream their own files from their own hardware.&lt;/p&gt;
&lt;p&gt;Plex’s core users provided the servers, the storage, the electricity, the libraries, the bug reports, the community, and in many cases lifetime payments made in good faith. Now those same users are being asked to pay more (ignoring of course that lifetimers are grandfathered at their pre-existing price for the lifetime of Plex the company), accept more cloud dependency, and tolerate a product strategy increasingly aimed somewhere else.&lt;/p&gt;
&lt;p&gt;Maybe Plex survives this by becoming a broader streaming portal with personal media as a legacy feature. But if that is the future, then I would rather move now to software whose incentives are aligned with self-hosting, ownership, and local control. That future is Jellyfin.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://images.unsplash.com/photo-1695509120014-83adf2b2d6e3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDMwfHx2aWRlbyUyMHJlbnRhbCUyMHN0b3JlfGVufDB8fHx8MTc3OTYzODE2N3ww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><category>technical</category></item><item><title>I read a book.</title><link>https://blog.ktz.me/i-read-a-book/</link><guid isPermaLink="false">6a1227ab02e4350001a456c7</guid><description>Earlier this year I decided to try and set myself the ambitious goal of reading a book. Yes, you read that right. One book.</description><pubDate>Sat, 23 May 2026 22:20:17 GMT</pubDate><content:encoded>&lt;img src=&quot;https://images.unsplash.com/photo-1581508525333-5fe25ad324f7?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ1fHxyZWQlMjBsaW5lfGVufDB8fHx8MTc3OTU3NDc2MHww&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=2000&quot; alt=&quot;I read a book.&quot;&gt;&lt;p&gt;The modern world has rotted my brain. I find focusing on anything that isn’t designed to hijack my dopamine stream very difficult. Earlier this year I decided to try and set myself the &lt;em&gt;ambitious goal&lt;/em&gt; of reading a book. Yes, you read that right. One book.&lt;/p&gt;
&lt;p&gt;I haven’t actually finished a book cover to cover in… I don’t even know. Years, at least. Probably a decade or more. That’s insane.&lt;/p&gt;
&lt;p&gt;So, I bought a Kobo Clara Color, spent a month setting up an elaborate Rube Goldberg machine to wirelessly sync any epub I could get my hands on wirelessly via an OPDS stream and then finally gave in and started reading.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This review contains massive spoilers!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;project-hail-mary&quot;&gt;Project Hail Mary&lt;br&gt;&lt;/h2&gt;
&lt;p&gt;The book begins completely grounded in reality. Science we all know and are familiar with. Despite the Sun dimming bacteria Astrophage being fiction, the author fitted them so plausibly into the real universe that I was able to suspend disbelief masterfully.&lt;/p&gt;
&lt;p&gt;Andy Weir, author of &lt;em&gt;Project Hail Mary&lt;/em&gt; and &lt;em&gt;The Martian&lt;/em&gt;, created a star killing bacteria so powerful that it united humanity as one. The world killing dilemma as a reader was quite compelling too. The idea that if politics were no longer a factor, and if science had a blank cheque, we could build an interstellar space ship to save our species? A refreshing thought in these tumultuous times, even if we must charitably permit the small matter of a hitherto unfeasibly energy dense fuel to enable it.&lt;/p&gt;
&lt;p&gt;The narrative flowed easily. The first half of the book was enjoyable but not gripping. Then we met Rocky.&lt;/p&gt;
&lt;p&gt;Rocky was playful, empathetic, skillful, and an &lt;em&gt;alien&lt;/em&gt;. After Rocky showed up I knew I was going to finish this book. I just had to!&lt;/p&gt;
&lt;p&gt;Rocky explaining without language, via molecule models, his atmospheric conditions? Genius. Making me understand just enough to be dangerous about evolution and molecular biology (Astrophage evolving Xenonite resistance like a tennis ball finding a way through a forest being a prime example).&lt;/p&gt;
&lt;p&gt;Generally speaking the book was what I imagine to be an almost perfect example of great sci-fi writing. Lots of concepts explained &lt;em&gt;just enough&lt;/em&gt; to further the story without being overwhelmingly dense. Although I will admit to a couple of moments of bamboozlement to some of the more complicated topics. In general though, I think this is &lt;em&gt;Andy Weir’s&lt;/em&gt; biggest strength. I am not a scientist, but this book left me feeling like I could have been if I’d had a teacher like Andy at some point in my life.&lt;/p&gt;
&lt;p&gt;By far the most gripping section of the book is after the Adrian biomatter collection. I felt real loss, or at least I thought I was about to, for Rocky. The whole moment where Rocky broke out of his atmospheric containment to save our human hero Ryland Grace was emotionally charged and that night I stayed up late frantically turning page after page to find out what happened. Great storytelling.&lt;/p&gt;
&lt;p&gt;Toward the end of the book, once our hero Ryland had made his final decision whether to return home or not, I felt like &lt;em&gt;Andy Weir&lt;/em&gt; was kinda done with the story and the ending felt rushed. A version of the ending where we found out how Earth reacted to “The Beetles” return (surely they would build a second Hail Mary to come and meet the Eridanians?!) would have been most welcome. By this point in the story I wasn’t too bothered by how Earth resolved their Astrophage problems, but humanity becoming a space faring species, knowing that there’s actually life out there? C’mon, the ending robbed us of that.&lt;/p&gt;
&lt;h4 id=&quot;the-movie&quot;&gt;The Movie&lt;/h4&gt;
&lt;p&gt;I waited to watch the movie until &lt;em&gt;after&lt;/em&gt; I’d read the book. I suppose the last time I did that was probably &lt;em&gt;The Hobbit&lt;/em&gt;, mostly because the movie took another 20 years to materialise.&lt;/p&gt;
&lt;p&gt;The movie got some things really right, like Rocky and the overall sense of humour. Ryan Gosling was great. But how the fuck can you do a movie about a sci-fi book and remove practically all the science? I’m fairly sure the word &lt;em&gt;celcius&lt;/em&gt; was not in the script anywhere.&lt;/p&gt;
&lt;p&gt;I think I would have enjoyed the movie without having read the book, but &lt;em&gt;because&lt;/em&gt; I read the book, I didn’t. Visually they got a lot right, which is always very subjective. But the alien spaceship was quite wrong, as was Rylands Eridanian biome at the end.&lt;/p&gt;
&lt;p&gt;The movie did agree with me on point though, that we should know at least a little bit about how Earth reacted to the return of &lt;em&gt;The Beetles&lt;/em&gt;.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://images.unsplash.com/photo-1581508525333-5fe25ad324f7?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ1fHxyZWQlMjBsaW5lfGVufDB8fHx8MTc3OTU3NDc2MHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><category>book-review</category></item><item><title>Codex is changing how I think about computers</title><link>https://blog.ktz.me/codex-is-changing-how-i-think-about-computers/</link><guid isPermaLink="false">6a0e3f2b02e4350001a4568c</guid><description>There is no doubt we&apos;re living through a seismic change in how we interface with computers. I have spent the last 15+ years learning a craft, how to adminster and interface with Linux. But I&apos;m starting to feel a shift in my own behaviours, which fills me with awe and simultaneously makes me deeply uncomfortable. I wanted to take a moment to share a slice of that journey with you today.


Tea. Earl Grey. Hot.

Picture this. Sitting on the couch with my 5yo daughter watching a new favourite show o</description><pubDate>Wed, 20 May 2026 23:24:21 GMT</pubDate><content:encoded>&lt;img src=&quot;https://images.unsplash.com/photo-1724185773486-0b39642e607e?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fHNvdW5kd2F2ZXxlbnwwfHx8fDE3NzkzMTk0MTR8MA&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=2000&quot; alt=&quot;Codex is changing how I think about computers&quot;&gt;&lt;p&gt;There is no doubt we’re living through a seismic change in how we interface with computers. I have spent the last 15+ years learning a craft, how to adminster and interface with Linux. But I’m starting to feel a shift in my own behaviours, which fills me with awe and simultaneously makes me deeply uncomfortable. I wanted to take a moment to share a slice of that journey with you today.&lt;/p&gt;
&lt;h2 id=&quot;tea-earl-grey-hot&quot;&gt;Tea. Earl Grey. Hot.&lt;/h2&gt;
&lt;p&gt;Picture this. Sitting on the couch with my 5yo daughter watching a new favourite show of hers named “The Creature Cases”. The episode starts playing, in Arabic. She squeaks. I have to put down &lt;em&gt;Project Hail Mary&lt;/em&gt; during the penultimate chapter (the humanity!), to navigate the incomprehensible Apple TV Plex on screen menu system and select from one of 28! audio tracks.&lt;/p&gt;
&lt;p&gt;“I should set up FileFlows or tdarr and really remove all those unneeded audio tracks” I think. Or maybe I can throw codex at the problem.&lt;/p&gt;
&lt;p&gt;9 mins later (less than one episode), we’re done. I didn’t leave the couch or the kid and disappear into a sysadmin hole. I just spent the rest of the evening with my kid. Nice.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-width-full&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/05/image.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1118&quot; height=&quot;916&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/05/image.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/05/image.png 1000w&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 720px) 720px, 90vw&quot;&gt;&lt;/figure&gt;
&lt;p&gt;See below for a nuanced take on what I really think of AI as a whole. But isn’t that kind of incredible? Like, actually though?&lt;/p&gt;
&lt;p&gt;I didn’t have to know anything about how the machine worked. This democractises technology in a way that few previous generations have experienced and &lt;em&gt;man&lt;/em&gt; is that exciting.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;I want you to know that AI was not used at all to write the text of this article. Just for the avoidance of doubt.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;kg-card kg-embed-card kg-card-hascaption&quot;&gt;&lt;iframe width=&quot;200&quot; height=&quot;113&quot; src=&quot;https://www.youtube.com/embed/_jBRSVFXLEk?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; title=&quot;I had to see the scale for myself to understand&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;&lt;figcaption&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;I&apos;m still trying to figure out where this all goes&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://images.unsplash.com/photo-1724185773486-0b39642e607e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fHNvdW5kd2F2ZXxlbnwwfHx8fDE3NzkzMTk0MTR8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><category>technical</category><category>ai</category><category>codex</category></item><item><title>Factorio: Controlling imports from Space</title><link>https://blog.ktz.me/factorio-controlling-imports-from-space/</link><guid isPermaLink="false">69d97c1b32a26c0001d5d5ea</guid><description>Only import what you need from space by reading the contents of your logistics network from a Roboport</description><pubDate>Fri, 10 Apr 2026 23:25:39 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-10-at-18.38.42.png&quot; alt=&quot;Factorio: Controlling imports from Space&quot;&gt;&lt;p&gt;Interplanetary logistics are a fundamental component of Factorio Space Age. It is puzzling to me why this particular aspect of the game feels half finished in what is otherwise a masterpiece of a game.&lt;/p&gt;
&lt;p&gt;Anyway, the problem at hand is this. I want to import items from one planet to another planet. Not an endless supply, though. Just the right amount. We can achieve this by using combinators to read the current number of items in the logistics network on a specific surface (planet) and comparing that with values we set in a constant combinator. The delta between those two values is what we want to import.&lt;/p&gt;
&lt;p&gt;The first step is to hook up a Roboport with a wire (red in my case)&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-14.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;682&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-14.png 600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Read the logistics network contents from a Roboport&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We need to configure the Roboport to &lt;code&gt;Read logistic network contents&lt;/code&gt; . This is so that all the items in the logistics network that this Roboport belongs to are made available to the circuit network.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-15.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1050&quot; height=&quot;652&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-15.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-15.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Set &quot;Read logistic network contents&quot;&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now we configure an Arithmetic combinator to multiply everything from the input by -1 so we get a negative number and output it. Configure &lt;code&gt;INPUT: EACH * -1 / OUTPUT: EACH&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-16.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1342&quot; height=&quot;728&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-16.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-16.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Take each item in the logistics network and multiply by -1 to give us a negative number&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now we hook up the Arithmetic combinator output to a Decider combinator input (I used a red wire in my example). Now hook up a Constant combinator configured with the numbers of items you want to import to the Decider combinator input (I used a green wire in my example).&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-17.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1294&quot; height=&quot;934&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-17.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-17.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The decider combinator (top) essentially compares Red (logistics) to Green (I want X)&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The constant combinator makes liberal use of logistics groups. These are such a great feature. Particularly if you’re able to utilize &lt;code&gt;5x GROUP&lt;/code&gt; to make sure you have a nice buffer of certain items in one place without having to keep separate groups for different use cases.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-18.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;672&quot; height=&quot;1400&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-18.png 600w&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 720px) 720px, 90vw&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Logistics groups are very useful&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now, we need to configure the Decider combinator to compare the Red inputs to the Green inputs and output the delta to send to space.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-19.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1336&quot; height=&quot;990&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-19.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-19.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Before: We need to import 10k green transport belts&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We configure the Decider combinator &lt;code&gt;Conditions: EACH ≥ 1 - Outputs: EACH Input count&lt;/code&gt;. This subtracts the red signals from the green signals, so that anything with a positive number gets imported (if present on a Space ship).&lt;/p&gt;
&lt;p&gt;For example, note above that we have a -100 Blue Circuit signal. Below I have added 50k green transport belts into my logistics network, which makes for an easy comparison to see the combinator in action.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-20.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1338&quot; height=&quot;988&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-20.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-20.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;After: We have a surplus of green transport belts so they are no longer an output (request)&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The last step to actually send these requests to space ships is to hook up the output from the Decider to the Cargo landing pad building and set &lt;code&gt;Set requests&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-21.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1588&quot; height=&quot;862&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-21.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-21.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Note &quot;Controlled by circuit network&quot;&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;With this in place you will never over import a specific product from space again. I’ve found this really helped keep rockets on other planets available for other purposes instead of spamming ships full of the same items over and over and over. Especially in the early stages of space where your remote bases might be less capable.&lt;/p&gt;
&lt;p&gt;Again though, I’m left wondering, why can’t we just have interplanetary logistics networks? Make it an end game tech or something idk. But anyway, until we get that this will have to do.&lt;/p&gt;
&lt;h3 id=&quot;bonus-tip-what-if-you-have-multiple-logistics-networks-on-one-surface&quot;&gt;Bonus Tip: What if you have multiple logistics networks on one surface?&lt;/h3&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-22.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1622&quot; height=&quot;824&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-22.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-22.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image-22.png 1600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Radars can &quot;teleport&quot; circuit signals from one radar to another on the same surface&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Use Radars to hook them up! The remote side Roboport is set to the same `Read logistics network contents` and then the red wire is hooked up to the Radar. Then we import the radar signal (on the red wire) to the input of the Arithmetic combinator like we did before.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-23.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1186&quot; height=&quot;906&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-23.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-23.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Happy Factories. Go Artemis II (this post published during reentry).&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-10-at-18.38.42.png" medium="image"/><category>factorio</category></item><item><title>Factorio: Controlling Space Ship collector filters via circuit logic</title><link>https://blog.ktz.me/factorio-controlling-space-ship-collectors-filters-via-circuit-logic/</link><guid isPermaLink="false">69d79f2132a26c0001d5d596</guid><description>Set Asteroid collector filters by reading the contents of a belt</description><pubDate>Thu, 09 Apr 2026 13:22:56 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-09-at-09.13.44.png&quot; alt=&quot;Factorio: Controlling Space Ship collector filters via circuit logic&quot;&gt;&lt;p&gt;In Factorio Space Age building Space Ships is a core part of the game. Gathering space rocks to process into raw materials is the most fundamental part of ship building. But how do you stop your ship filling up with just one type of space rock chunk?&lt;/p&gt;
&lt;p&gt;The solution involves a Space Age feature of reading belt contents.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-11.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;758&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-11.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-11.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Hook ups&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I design my ships typically with one big belt for all collectors to deposit their Asteroid chunks onto with no splits or other joins. This is because reading the belt contents only works for a single continuous belt sector. I could use circuits to sum up multiple sections but after a while this design constraint just becomes habit and you remove items with filtered inserters rather than splitters.&lt;/p&gt;
&lt;div class=&quot;kg-card kg-callout-card kg-callout-card-blue&quot;&gt;&lt;div class=&quot;kg-callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div class=&quot;kg-callout-text&quot;&gt;I use the mod &lt;a href=&quot;https://mods.factorio.com/mod/circuit_visualizer?ref=blog.ktz.me&quot; rel=&quot;noreferrer&quot;&gt;Circuit Visualizer&lt;/a&gt; to make it easier to see which circuit nodes hook up to what.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The first step on our journey, assuming we’ve placed collectors and have them outputting onto a belt, is to connect a single segment of belt to the input of a Decider combinator. Red or green doesn’t matter, just be consistent (I used red here). Set the belt to &lt;code&gt;Read belt contents - Hold (all belts)&lt;/code&gt; and this will provide the contents of that belt as an output to the circuit network to be used for conditional logic.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-09-at-09.18.02.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;434&quot; height=&quot;348&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Constant combinators hooked up to green input of Decider&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In order to tell the Decider how many chunks of each type we want I used a Constant combinator. This Constant was hooked up to the Deciders green input.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-09-at-09.18.10.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;790&quot; height=&quot;932&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/Screenshot-2026-04-09-at-09.18.10.png 600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Constant combinator. How many? Of what chunk type?&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Next we want to configure the Decider combinator to &lt;code&gt;compare the number of chunks on the belt&lt;/code&gt; vs &lt;code&gt;the number of chunks we&apos;d like on the belt&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-10.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1552&quot; height=&quot;998&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-10.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-10.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The decider decides which output signals are sent to the Asteroid collectors&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now we can evaluate RED vs GREEN like so: &lt;code&gt;IF RED INPUT (chunks on belt) IS &amp;lt; GREEN INPUT (chunks we want) THEN OUTPUT CHUNK TYPE&lt;/code&gt;. We can do this using the &lt;code&gt;EACH&lt;/code&gt; operator represented by the yellow icon with 3 lines.&lt;/p&gt;
&lt;p&gt;The Decider will only output a chunk signal if the conditional is TRUE for EACH chunk type.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-12.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1598&quot; height=&quot;874&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-12.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-12.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The green wire connects all Asteroid collectors together.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Next, hook up the output of the Decider to all Asteroid collectors at once. The configure each collector with &lt;code&gt;SET FILTERS&lt;/code&gt; to allow the circuit network to control them.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-13.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1154&quot; height=&quot;590&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-13.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-13.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Notice that the collector is disabled because all requested chunks are present on the belts&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;And there we have it. Each Asteroid collector will now only collect the chunk types required to fulfil the conditional logic&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-09-at-09.13.44.png" medium="image"/><category>factorio</category></item><item><title>Factorio: Recycler Belt Stacking</title><link>https://blog.ktz.me/factorio-recycler-belt-stacking/</link><guid isPermaLink="false">69d6d84032a26c0001d5d517</guid><description>Maximised Recycler efficiency by using Stack Inserters and the Circuit Network</description><pubDate>Wed, 08 Apr 2026 23:56:20 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-08-at-18.28.28.png&quot; alt=&quot;Factorio: Recycler Belt Stacking&quot;&gt;&lt;p&gt;Circuit logic in Factorio is pretty annoying to deal with, tbh. I really wish there was a way to deterministically configure circuits with expressions. Alas, here we are.&lt;/p&gt;
&lt;p&gt;In this post, I’ll walk through a solution to using a recycler in &lt;a href=&quot;https://www.factorio.com/?ref=blog.ktz.me&quot;&gt;Factorio&lt;/a&gt; with a stack inserter without it jamming. There are definitely other approaches, but this is the one that worked for me.&lt;/p&gt;
&lt;p&gt;There’s a blueprint string at the end if you’d like it.&lt;/p&gt;
&lt;h2 id=&quot;recycling-junk&quot;&gt;Recycling Junk&lt;/h2&gt;
&lt;p&gt;Recyclers are unlocked on Fulgora and although their primary use is for recycling Scrap into the 12 output products, this is not their only use. We can also use Recyclers to upcycle items &lt;a href=&quot;https://wiki.factorio.com/Quality?ref=blog.ktz.me&quot;&gt;quality&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1580&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image.png 1600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w2400/2026/04/image.png 2400w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The standard scrap recycling recipe in Factorio&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Quality brings 5 tiers of items to the game, each with increasingly powerful stats. Thus, even a simple Scrap recycling recipe can potentially have 60 product possibilities. Upcycling only excerbates the number of possible output products.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-08-at-18.28.42.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1204&quot; height=&quot;944&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/Screenshot-2026-04-08-at-18.28.42.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/Screenshot-2026-04-08-at-18.28.42.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;A simple quality upcycling example&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This is a problem for stack inserters, which only swing when they have a full stack of 16 items. If a machine is outputting just 1 or 2 of something, the inserter won’t clear its output until it reaches 16 - or as we sometimes refer to it, it will &lt;em&gt;jam&lt;/em&gt;. If you’re dealing with mixed outputs or qualities and not using filters, you’re going to have a bad time.&lt;/p&gt;
&lt;p&gt;So we need a way to buffer items until there are 16 of a kind, and dynamically set the inserter’s filters so it only picks up items that have reached that threshold.&lt;/p&gt;
&lt;h2 id=&quot;circuit-city&quot;&gt;Circuit City&lt;/h2&gt;
&lt;p&gt;To make this next section easier to visualise I’m using the mod [Circuit Visualizer](&lt;a href=&quot;https://mods.factorio.com/mod/circuit_visualizer?ref=blog.ktz.me&quot;&gt;https://mods.factorio.com/mod/circuit_visualizer&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;First, we need a way to buffer items until we have a full stack of them. For this, we use chests. Place one at the output of your Recycler.&lt;/p&gt;
&lt;p&gt;Next, we must count the items in the chests. For this, we use an arithmetic combinator and red wires linking every chest to the combinators input.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-1.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1774&quot; height=&quot;1302&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-1.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-1.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image-1.png 1600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Hook up a red wire to every chest and connect it to the input of the Arithmetic combinator&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Configure the Arithmetic combinator to output a signal of value 1 for each item present in the chests. Conditions should be &lt;code&gt;EACH &amp;gt; 0&lt;/code&gt; and Outputs &lt;code&gt;EACH 1&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-2.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1776&quot; height=&quot;1062&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-2.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-2.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image-2.png 1600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Arithmetic combinator configuration.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We can think of the Arithmetic combinator like an &lt;em&gt;if&lt;/em&gt; statement. If an item is present in any quantity greater than 0, then output a signal via the combinators output.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-3.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;628&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-3.png 600w&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 720px) 720px, 90vw&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Connecting the Arithmetic output to the Deciders input via a Green Wire&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now hook up the output of the Arithmetic combinator using a green wire (colour is important) the input of a Decider combinator.&lt;/p&gt;
&lt;p&gt;We must also hook up every Stack Inserter via a red wire to the output of the Decider.&lt;/p&gt;
&lt;p&gt;Configure the Decider like so: &lt;code&gt;INPUT -&amp;gt; EACH - 16&lt;/code&gt; / &lt;code&gt;OUTPUT EACH&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-4.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1774&quot; height=&quot;956&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-4.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-4.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image-4.png 1600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;p&gt;The job of the decider combinator is to subtract 16 from every signal that comes in thus creating an index of available items to filter. By sending this signal out as -15 we can then compare the contents of the chest to this value and only once it is 16+ (a full load) does the Stack inserters filter become set.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-7.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1178&quot; height=&quot;622&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-7.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-7.png 1000w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The Stack Inserter should be configured like so&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The final piece here is hook up a green wire from the chests to each Stack inserter, one by one. Then configure the Stack Inserter to &lt;code&gt;ENABLE/DISABLE when ANYTHING &amp;gt; 2&lt;/code&gt; and &lt;code&gt;SET FILTERS&lt;/code&gt; is checked. The Stack Inserter reads the filters from the circuit network. Do not link these down the line as you have the chests or inserters previously.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/image-5.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1232&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/04/image-5.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2026/04/image-5.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2026/04/image-5.png 1600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Hook up a single green wire connecting the chest to the Stack Inserter&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;sit-back-and-relax&quot;&gt;Sit back, and relax&lt;/h2&gt;
&lt;p&gt;Now sit back and watch the fruits of your hard work.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/recycler-magnified.gif&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;360&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/recycler-magnified.gif 640w&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;The final result&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;When the chest contains 17 of something then it’s OK to swing. The chest contains multiple tiers of quality items and scales as far as I have been able to test to infinite number of items.&lt;/p&gt;
&lt;p&gt;The only real downside is that this won’t work in space because you can’t place chests there.&lt;/p&gt;
&lt;p&gt;Here’s a blueprint string for you to try it out yourself - I’m in the blueprint sandboxes mod for all of these screenshots.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;0eNrlWNuSoyoU/ReecUrwEk3VnB/pSlmopEONogcx56S6/PfZqNF0Yroxvs08RTew1mbti5APlBYtr5WQGu0/kMgq2aD92wdqxLtkhbFJVnK0R4pnl6zgCnUYCZnz/9GedHhhom5VWjlaMdnUldJOygt9s4h2B4y41EILPlD1L5dEtmUK8HuCv0TCqK4aWFxJwwmAjkd2PwKMLmgfBj8CYMoFODvMiIyLdwR0A4FvQ+BNBI1m2S9HyIYrDSNL0OFTaH8B2p+ghTwKCUNOduLNstfBZ+jriqThWgv53piZipfVmSctjBXgIs8ToXkJQ0dWNByjwTwEamSuC9ZokTkpMzvKqtbkDnFdjMoqNxOYdgrOeqemTDl0C7sJpt0wJfSp5AY2q8pUSKarZb3cKdadIZdaVUWS8hM7C1gB02aoBIbzfnm/1aNQjU7mfNWX2lCfhdItWOag9TMczrKTyduGGxiDBdHstxpiVNVcscEx5MDSqtV1uxq8WxIlnObmPBM5V98pQr5TZMS5k+P27e1ldcC3mqnetz36B5niHrS4byPWePUl6XMqOaqqTIQErDEbTRItCLbbUM87m3qONhCENgTxSw3jAZrQBWzi4ocWvgTrj4Lc9SAo4aEfQDBFftPm/4UomvYDNd8W3PH6Fj9MhZkSAncGTyp1GZbObwDZ7xLtXePu4gh5OkKfjngmPQ5LCpA18rpfyLtcXplQWSt0wiVLCw4aadVC57yapzp7oQcxedEnaNVDZVwbEH0su5kOmnsyNW3jCYy1Db+3PapEb1TivPjiu0JuJVqC8lYXjBuvqkjib2CwKkkSbCj6yIohfKnqI7uq362q+vgPrPpofT5HT/I5fqmBRH9XA6Huhpq0qhh6fzVoakjGJ3Fw4zG1H5Cvh9qbtP58pB2THOwFf+cyZ5Byd4r9NIqNhz64PVXqOv9o7jqPntMVGeROtR5bqeLZJrobfpPodENb3RErZ4MNDK4VQ7ieIXrKsHQHo+sPnJPylgzrT5zubh3D3NLStrDsaDtqA+25a+6o5DP2ujtq34mWXCD2u5uDT62+rB7dkMHU6u8Db4WAc9xfFxDubP+BS+Zz/xZgikPsHzA8eRiOzgQeQwy/tH80FgwfxPGZGjs1z9TYo8EeGXsM9sNwOjBxmP5mwugMn5F+D0FIYz+Og8h3qetHXfcbT7ktQw==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/04/Screenshot-2026-04-08-at-18.28.28.png" medium="image"/><category>factorio</category></item><item><title>Was Solar Worth It?</title><link>https://blog.ktz.me/was-solar-worth-it/</link><guid isPermaLink="false">69668a5b0abb560001a32332</guid><description>In NC where the sun shines a lot, but electricity from The Grid is cheap what is the ROI on an 8kw solar system?</description><pubDate>Tue, 13 Jan 2026 18:30:02 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/01/IMG_3373.JPG&quot; alt=&quot;Was Solar Worth It?&quot;&gt;&lt;p&gt;I wanted a clear answer to a simple question: &lt;strong&gt;is my solar system paying off?&lt;/strong&gt; So I pulled real data from my Duke Energy bills and SolarEdge monitoring and ran the numbers.&lt;/p&gt;
&lt;p&gt;Below is a plain-English breakdown of the system, the numbers, and the ROI.&lt;/p&gt;
&lt;h2 id=&quot;the-system&quot;&gt;The System&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Installed:&lt;/strong&gt; June 7, 2021&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System size:&lt;/strong&gt; 8.16 kWp&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inverter:&lt;/strong&gt; SolarEdge SE7600H&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimizers:&lt;/strong&gt; 24 × P401&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-i-paid&quot;&gt;What I Paid&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Total system price:&lt;/strong&gt; $23,223&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loan terms:&lt;/strong&gt; 1.49% for 20 years
&lt;ul&gt;
&lt;li&gt;Estimated payment: &lt;strong&gt;$122.32/mo&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federal tax credit claimed:&lt;/strong&gt; &lt;strong&gt;$6,500&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So my &lt;strong&gt;net cost&lt;/strong&gt; after the tax credit is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;$16,723&lt;/strong&gt; (using contract price)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;net-metering-assumption&quot;&gt;Net Metering Assumption&lt;/h2&gt;
&lt;p&gt;I reviewed the last year of my Duke Energy Progress bills and came up with some asnwers. Exports are &lt;strong&gt;netted 1:1 at the retail rate within each billing period&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Would a battery help? Short answer: no — not right now. Because Duke’s 1:1 net metering already gives me full retail value for exports within the billing period, so a battery doesn’t add much financial benefit. It could add backup power, but for ROI it’s hard to justify. The only scenario where that changes is if Duke moves to time‑of‑use rates or reduces export credits. Under TOU, a battery could help by shifting solar into expensive evening hours — but until that happens, net metering does the same job for free.&lt;/p&gt;
&lt;h2 id=&quot;2025-snapshot-usage-production&quot;&gt;2025 Snapshot (Usage + Production)&lt;/h2&gt;
&lt;p&gt;From Duke Energy bills (12 unique 2025 bills) and SolarEdge:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Grid import (Energy Used):&lt;/strong&gt; 15,858 kWh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grid export (Energy Delivered):&lt;/strong&gt; 2,409 kWh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Net billed usage:&lt;/strong&gt; 13,449 kWh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SolarEdge production:&lt;/strong&gt; 6,663 kWh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blended rate (all charges):&lt;/strong&gt; ~$0.163/kWh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt;&lt;br&gt;
In &lt;strong&gt;Jan–Mar 2025&lt;/strong&gt; the inverter stopped producing for about &lt;strong&gt;10 weeks&lt;/strong&gt;. I didn’t notice right away because the Wi‑Fi monitoring was throwing false positives. I’ve now &lt;strong&gt;hard-wired the inverter&lt;/strong&gt; to fix that. It turns out a &lt;strong&gt;simple reboot&lt;/strong&gt; was all that was needed, but it was still frustrating to lose ~2.5 months of production.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/01/Screenshot-2026-01-13-at-14.06.38-1.png&quot; alt=&quot;Screenshot 2026-01-13 at 14.06.38.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;annual-savings-estimate-year-by-year&quot;&gt;Annual Savings Estimate (Year by Year)&lt;/h2&gt;
&lt;p&gt;Using the 2025 blended Duke rate ($0.163/kWh) applied to SolarEdge production:&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;right&quot;&gt;Year&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Solar production (kWh)&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Estimated savings ($)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;2021&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;4,565&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;744.55&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;2022&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;7,495&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,222.40&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;2023&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;8,042&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,311.71&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;2024&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;6,833&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,114.41&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;2025&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;6,663&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,086.70&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;roi-and-payback&quot;&gt;ROI and Payback&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Simple payback&lt;/strong&gt; (no inflation or escalation):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Net cost: &lt;strong&gt;$16,723&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Payback: &lt;strong&gt;~15.4 years&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;ROI: &lt;strong&gt;~6.5%/yr&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2025-monthly-detail-from-bills&quot;&gt;2025 Monthly Detail (From Bills)&lt;/h2&gt;













































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Bill date&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Billing period&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Import (kWh)&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Export (kWh)&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Net billed (kWh)&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Charges ($)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Jan 27, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Dec 21–Jan 23&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,578&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;157&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,421&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;220.07&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Feb 26, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Jan 24–Feb 24&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,554&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;99&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,455&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;224.98&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Mar 26, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Feb 25–Mar 24&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,276&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;0&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,276&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;200.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Apr 25, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Mar 25–Apr 23&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,465&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;115&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,350&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;213.47&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;May 27, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Apr 24–May 22&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,175&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;347&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;828&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;143.30&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Jun 25, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;May 23–Jun 23&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,353&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;287&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,066&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;178.22&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Jul 28, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Jun 24–Jul 24&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;2,038&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;99&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,939&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;305.59&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Aug 26, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Jul 25–Aug 22&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,598&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;128&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,470&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;236.77&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Sep 25, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Aug 23–Sep 23&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1,276&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;315&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;961&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;162.29&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Oct 28, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Sep 24–Oct 24&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;886&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;363&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;523&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;100.38&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Nov 24, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Oct 25–Nov 21&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;680&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;366&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;314&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;70.08&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Dec 26, 2025&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Nov 22–Dec 22&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;979&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;133&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;846&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;152.02&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;chart-estimated-solar-production-vs-net-billed-2025&quot;&gt;Chart: Estimated Solar Production vs Net Billed (2025)&lt;/h2&gt;
&lt;p&gt;This chart uses bill data plus a simple self-consumption ratio to estimate monthly solar production. It is directional, not exact, and will not perfectly match the annual SolarEdge total.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Jan | P:############ (587) B:---------------------------- (1421)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Feb | P:########## (523) B:----------------------------- (1455)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Mar | P:####### (348) B:-------------------------- (1276)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Apr | P:########## (515) B:--------------------------- (1350)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;May | P:############# (668) B:----------------- (828)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Jun | P:############# (656) B:--------------------- (1066)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Jul | P:############# (655) B:--------------------------------------- (1939)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Aug | P:########### (564) B:----------------------------- (1470)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Sep | P:############# (663) B:------------------- (961)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Oct | P:############ (605) B:---------- (523)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Nov | P:########### (551) B:------ (314)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Dec | P:######## (400) B:----------------- (846)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/01/IMG_20210607_085830.jpg&quot; alt=&quot;IMG_20210607_085830.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h2&gt;
&lt;p&gt;Based on real 2025 billing data and SolarEdge production, the system is on track for a &lt;strong&gt;15 year payback&lt;/strong&gt; and a &lt;strong&gt;~6% simple ROI&lt;/strong&gt; after the federal tax credit. That’s not as good as I’d hoped honestly. But, it’s a solid, predictable savings — and likely improves as electricity rates rise.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/01/photo_2026-01-13-13.15.22.jpeg&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;960&quot; height=&quot;1280&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2026/01/photo_2026-01-13-13.15.22.jpeg 600w&quot; sizes=&quot;(min-width: 720px) 720px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2026/01/IMG_3373.JPG" medium="image"/><category>technical</category><category>solar</category></item><item><title>AppArmor&apos;s Awkward Aftermath Atop Proxmox 9</title><link>https://blog.ktz.me/apparmors-awkward-aftermath-atop-proxmox-9/</link><guid isPermaLink="false">690fef12405f1d000176723f</guid><description>Proxmox 9 looks great, but AppArmor keeps getting in the way</description><pubDate>Sun, 09 Nov 2025 01:48:23 GMT</pubDate><content:encoded>&lt;img src=&quot;https://images.unsplash.com/photo-1623681153891-2d2dc711beb0?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGhhcmQlMjB0byUyMGxvdmV8ZW58MHx8fHwxNzYyNjUyODkwfDA&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=2000&quot; alt=&quot;AppArmor&apos;s Awkward Aftermath Atop Proxmox 9&quot;&gt;&lt;p&gt;If you run Docker inside LXC containers on Proxmox you probably woke up this week to a fun surprise. Your containers won’t start anymore. The error looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: open sysctl net.ipv4.ip_unprivileged_port_start file: reopen fd 8: permission denied: unknown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This isn’t a Proxmox bug. It’s not even really a Docker bug. It’s a security patch that landed in &lt;a href=&quot;https://github.com/containerd/containerd/issues/12484?ref=blog.ktz.me&quot;&gt;containerd.io version 1.7.28-2&lt;/a&gt; around November 5th fixing CVE-2025-52881, a critical container escape vulnerability. The fix involves reopening file descriptors for procfs operations which triggers AppArmor permission errors when running Docker inside nested LXC containers.&lt;/p&gt;
&lt;p&gt;The technical details are actually kind of fascinating. Bear with me, I’ll make it as simple as I can.&lt;/p&gt;
&lt;h2 id=&quot;a-quick-detached-mounts-sidebar&quot;&gt;A quick detached mounts sidebar&lt;/h2&gt;
&lt;p&gt;A detached mount is a filesystem mount that exists in the kernel but isn’t attached to any path in the filesystem tree. Think of it like a mounted filesystem that’s floating in memory without a mountpoint.&lt;/p&gt;
&lt;p&gt;Normally when you mount something, it gets attached to a specific path thus:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;mount&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /dev/sda1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /mnt/data&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;  # attached to /mnt/data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A detached mount exists but has no path. You can only access it through file descriptors. Runc uses detached mounts as a security feature to avoid race conditions where an attacker could swap out mountpoints while runc is trying to access them.&lt;/p&gt;
&lt;p&gt;The problem is that when the kernel tries to generate a pathname for files inside a detached mount (which AppArmor needs since it’s path-based), it can only see the relative path from the mount root. So &lt;code&gt;/proc/sys/net/ipv4/ip_unprivileged_port_start&lt;/code&gt; inside a detached procfs mount just looks like &lt;code&gt;/sys/net/ipv4/ip_unprivileged_port_start&lt;/code&gt; to AppArmor because the &lt;code&gt;/proc&lt;/code&gt; part doesn’t exist in the filesystem tree.&lt;/p&gt;
&lt;p&gt;It’s basically a mismatch between two security features: runc’s use of detached mounts to prevent path-based attacks, and AppArmor’s path-based access control system that needs actual paths to make decisions.&lt;/p&gt;
&lt;p&gt;In case you were curious, SELinux wouldn’t have this problem because it’s label-based rather than path-based.&lt;/p&gt;
&lt;p&gt;SELinux assigns security labels (contexts) directly to files, processes, and other objects. When you access a file, SELinux checks if your process label is allowed to perform that action on the file’s label.&lt;/p&gt;
&lt;h2 id=&quot;how-we-do-fix-this&quot;&gt;How we do fix this?&lt;/h2&gt;
&lt;p&gt;For now, the only way &lt;a href=&quot;https://github.com/opencontainers/runc/issues/4968?ref=blog.ktz.me&quot;&gt;I could find&lt;/a&gt; is to disable AppArmor entirely on a per LXC basis. Not exactly the ideal long term solution but for now, the only one available.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;lxc.apparmor.profile: unconfined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;lxc.mount.entry: /dev/null sys/module/apparmor/parameters/enabled none bind 0 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OR&lt;/p&gt;
&lt;p&gt;As per this comment you can trick Docker into thinking AppArmor is disabled. Also yuck.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;% mount --bind /dev/null /sys/module/apparmor/parameters/enabled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;% systemctl restart docker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;apparmor-you-are-making-this-hard&quot;&gt;AppArmor, you are making this hard&lt;/h2&gt;
&lt;p&gt;Look, I get it. AppArmor exists for good reasons. It provides mandatory access control and helps contain potential security issues. But for homelab users and small deployments this stuff is beginning to get exhausting. This is not my first frustration with AppArmor since adopting Proxmox 9 a few months ago. The enterprise folks have teams to deal with this crap, the rest of us are just trying to run some containers.&lt;/p&gt;
&lt;p&gt;Unfortunately, I just do not believe AppArmor is not fit for purpose, nor was Proxmox diligent or rigorous in their including it in Proxmox 9. I won’t belabor the point any further here but I did &lt;a href=&quot;https://blog.ktz.me/proxmox-9-made-unprivileged-lxcs-pointless-for-quicksync-users/&quot;&gt;write about it recently&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Proxmox is genuinely great software. And I have made countless videos both at &lt;a href=&quot;https://www.youtube.com/tailscale?ref=blog.ktz.me&quot;&gt;work&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/@ktzsystems?ref=blog.ktz.me&quot;&gt;personally&lt;/a&gt; about it. The team does excellent work and the platform is rock solid for virtualization. But the AppArmor integration continues to be a source of friction that makes recommending it harder than it should be. I’m going to have to start to look for alternatives soon, not that there really are any. Ugh.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://images.unsplash.com/photo-1623681153891-2d2dc711beb0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGhhcmQlMjB0byUyMGxvdmV8ZW58MHx8fHwxNzYyNjUyODkwfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><category>technical</category><category>proxmox</category></item><item><title>Unprivileged LXCs are just a bit annoying</title><link>https://blog.ktz.me/proxmox-9-made-unprivileged-lxcs-pointless-for-quicksync-users/</link><guid isPermaLink="false">68db27612699110001831c6e</guid><description>Proxmox 9&apos;s AppArmor 4.1 upgrade broke Intel QuickSync monitoring in unprivileged LXC containers. The workarounds require such significant security compromises that privileged containers are arguably the only realistic option now. </description><pubDate>Tue, 30 Sep 2025 01:07:34 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/20210222_002939.jpg&quot; alt=&quot;Unprivileged LXCs are just a bit annoying&quot;&gt;&lt;p&gt;Proxmox 9 shipped with AppArmor 4.1 in August 2025, and the new security restrictions make Intel GPU “passthrough” with monitoring tools like &lt;code&gt;intel_gpu_top&lt;/code&gt; effectively impossible without either host-wide security reductions or abandoning the unprivileged model entirely.&lt;/p&gt;
&lt;p&gt;Recently, I documented &lt;a href=&quot;https://blog.ktz.me/proxmox-9-broke-my-docker-containers/&quot;&gt;a workaround&lt;/a&gt; for issues the new AppArmor release introduced in my configuration. This led to folks suggesting that running docker containers on the Linux Proxmox host itself was “&lt;em&gt;evil”&lt;/em&gt; (I jest but you know how comment sections can get).&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-card-hascaption&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/image.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;409&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2025/09/image.png 600w&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 720px) 720px, 90vw&quot;&gt;&lt;figcaption&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;Credit: Midwesternrodent at selfhosted.show/discord&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;So, to dogfood what the “just run it in an LXC crowd” were espousing, I decided to attempt to port my homelab to LXCs this weekend - and follow all best practices in the process.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It has not gone well&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-unprivileged-containers-matter&quot;&gt;Why unprivileged containers matter&lt;/h2&gt;
&lt;p&gt;In a privileged LXC container, root inside the container is the same as root on the host. Container escapes means full host compromise. And whilst these escapes are rare, the LXC security team &lt;a href=&quot;https://people.kernel.org/brauner/runtimes-and-the-curse-of-the-privileged-container?ref=blog.ktz.me&quot;&gt;doesn’t consider&lt;/a&gt; escape exploits in privileged containers as security issues because the isolation is minimal by design.&lt;/p&gt;
&lt;p&gt;Unprivileged containers use UID/GID mapping to run as high-numbered users (100000+) on the host whilst appearing as root (UID 0) inside. Even if an attacker escapes, they’re a nobody on the host with no privileges. It’s the difference between “rebuild the container” versus “rebuild your entire hypervisor.”&lt;/p&gt;
&lt;h2 id=&quot;whats-broken&quot;&gt;What&apos;s broken?&lt;/h2&gt;
&lt;p&gt;Proxmox VE 9.0 shipped with AppArmor 4.1, a major version jump from 3.x in the previous Proxmox release.&lt;/p&gt;
&lt;p&gt;With this new release, any attempt to run &lt;code&gt;intel_gpu_top&lt;/code&gt; in an unprivileged LXC fails with “Failed to initialize PMU! (Permission denied)” in unprivileged containers, even with correct GPU device passthrough. Privileged containers continue to work as you would expect.&lt;/p&gt;
&lt;p&gt;Here’s the frustrating part: &lt;strong&gt;GPU transcoding still works fine&lt;/strong&gt;. You can pass &lt;code&gt;/dev/dri/renderD128&lt;/code&gt; to your container and transcode just fine. Of course, we could just use &lt;code&gt;intel_gpu_top&lt;/code&gt; on the host itself but that’s not the point here is it?&lt;/p&gt;
&lt;p&gt;There’s also a great deal of complexity when it comes to mounting network shares and many other things the UID shifts introduce.&lt;/p&gt;
&lt;h2 id=&quot;why-it-fails-technically&quot;&gt;Why it fails technically&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;intel_gpu_top&lt;/code&gt; tool needs access to Intel’s PMU (Performance Monitoring Unit) through the Linux perf_events interface via the &lt;code&gt;perf_event_open()&lt;/code&gt; syscall. In unprivileged containers, this syscall crosses the UID remapping boundary. Container root (UID 0) becomes UID 100000+ on the host, and the kernel strips all capabilities.&lt;/p&gt;
&lt;p&gt;Modern Linux distributions set &lt;code&gt;kernel.perf_event_paranoid&lt;/code&gt; to 2 or higher (Debian/Ubuntu use 3-4), blocking performance monitoring for unprivileged users. Even setting it to -1 doesn’t help because of UID remapping. AppArmor 4.1’s stricter enforcement makes this worse.&lt;/p&gt;
&lt;h2 id=&quot;your-options-theyre-all-bad&quot;&gt;Your options (they&apos;re all bad)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Option 1: Host-wide kernel parameter changes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Set &lt;code&gt;kernel.perf_event_paranoid=0&lt;/code&gt; on your Proxmox host. This reduces security system-wide. Every container and VM can now access performance monitoring, potentially leaking information about other processes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option 2: Disable AppArmor confinement&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;lxc.apparmor.profile: unconfined&lt;/code&gt; to your container config. You’ve removed the mandatory access control layer that prevents container escapes. You’re left with just namespace isolation and UID mapping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option 3: Combine both&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many “successful” deployments use both workarounds. You’ve made host-wide security reductions AND disabled container-level protections just to monitor GPU usage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option 4: Run privileged containers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Set &lt;code&gt;unprivileged: 0&lt;/code&gt; and accept that root in your LXC container equals root on your host. &lt;strong&gt;At least you’re being honest about your security posture.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here’s the uncomfortable truth: if you’re already making host-wide kernel changes or disabling AppArmor, running privileged containers is arguably more pragmatic. You’ve already accepted substantial security reductions. Privileged containers at least give you full functionality without pretending you’ve maintained security through half-measures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option 5: Run privileged containers and rootless docker/podman&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We’re getting a bit into Inception spinning top territory here but what if we combine everything in option 4 - run the LXC as &lt;code&gt;unprivileged: 0&lt;/code&gt; but then also migrate our application containers to rootless podman? At least then we have the applications isolated from root as much as possible. Of course, not every container supports running rootless so this introduces its own set of problems. Sigh.&lt;/p&gt;
&lt;h2 id=&quot;proxmox-is-changing-with-enterprise-focus&quot;&gt;Proxmox is changing with enterprise focus&lt;/h2&gt;
&lt;p&gt;Proxmox has seen significant growth since Broadcom’s VMware pricing changes in late 2023. The project is now competing for corporate deployments that demand security certifications and compliance checkboxes. And in a world where you’re competing against Red Hat who have had SELinux for &lt;em&gt;years&lt;/em&gt; at this point AppArmor seems like an obvious W.&lt;/p&gt;
&lt;p&gt;And indeed, AppArmor 4.1’s aggressive security posture makes sense for that audience. The challenge is that Proxmox’s existing user base includes many homelabbers running exactly the workloads that broke, and we can be a bit of annoying, vocal bunch at times.. Media servers with QuickSync aren’t exactly your typical enterprise use case.&lt;/p&gt;
&lt;p&gt;Largely speaking theses changes are probably long term good for the Proxmox project in so much as they can make a business out of a truly excellent product. But is it good for the homelab user base that put them there overall? Time will tell.&lt;/p&gt;
&lt;h2 id=&quot;the-practical-path-forward&quot;&gt;The practical path forward&lt;/h2&gt;
&lt;p&gt;Every successful deployment of an unprivileged LXC in the forums I’ve been able to find involves either host-wide kernel changes, disabling AppArmor entirely, or both.&lt;/p&gt;
&lt;p&gt;The most pragmatic solution I can come up with? Install &lt;code&gt;intel-gpu-tools&lt;/code&gt; on the Proxmox host itself and run &lt;code&gt;intel_gpu_top&lt;/code&gt; there. It shows GPU usage from all containers without configuration changes. This defeats the point of containerized monitoring, but that’s where we are. Arguably it makes more sense to do it at the host level to get a holistic picture of the entire system so really you can argue this one either way.&lt;/p&gt;
&lt;p&gt;But if you’re running a homelab with QuickSync transcoding and need GPU monitoring, just run privileged containers. You’ve lost the security benefits anyway with host-wide kernel changes or unconfined AppArmor profiles.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;security theater&lt;/em&gt; of running “unprivileged” containers with &lt;code&gt;unconfined&lt;/code&gt; AppArmor and modified kernel parameters is just that: theater. You’re checking a box that says &lt;code&gt;unprivileged: 1&lt;/code&gt; whilst undermining the mechanisms that make unprivileged containers meaningful.&lt;/p&gt;
&lt;p&gt;Hopefully a solution comes along that will permit unprivileged LXCs to access a specific resource like the PMU but technically I do not know enough to know whether that’s even feasible. Until then, &lt;code&gt;unprivileged: 0&lt;/code&gt; it is.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/20210222_002939.jpg" medium="image"/><category>technical</category><category>quicksync</category><category>proxmox</category></item><item><title>My Terminal and Editor Theming</title><link>https://blog.ktz.me/my-terminal-and-editor-theming/</link><guid isPermaLink="false">68c4427e5878990001f6a448</guid><description>It&apos;s not ricing. Promise.</description><pubDate>Fri, 12 Sep 2025 16:07:44 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/Screenshot-2025-09-12-at-12.07.30.png&quot; alt=&quot;My Terminal and Editor Theming&quot;&gt;&lt;p&gt;As you may know, I make YouTube videos for Tailscale for a living. One of the most common questions in the comments I get (weirdly) is, “how do you theme your tools?”&lt;/p&gt;
&lt;p&gt;This post will set out to answer that question in more detail than I can provide in a simple comment reply.&lt;/p&gt;
&lt;h2 id=&quot;font&quot;&gt;Font&lt;/h2&gt;
&lt;p&gt;Where possible I use &lt;a href=&quot;https://usgraphics.com/products/berkeley-mono?ref=blog.ktz.me&quot;&gt;Berkeley Mono&lt;/a&gt;. Fira Code or Jetbrains Mono are nice fallbacks.&lt;/p&gt;
&lt;h2 id=&quot;terminal&quot;&gt;Terminal&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS terminal - &lt;a href=&quot;https://ghostty.org/?ref=blog.ktz.me&quot;&gt;ghostty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Linux terminal - omarchy defaults (&lt;a href=&quot;https://alacritty.org/?ref=blog.ktz.me&quot;&gt;A&lt;/a&gt;&lt;a href=&quot;https://alacritty.org/?ref=blog.ktz.me&quot;&gt;lacritty&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s my ghostty config.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# appearance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;font-family&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &quot;BerkeleyMono Nerd Font&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;font-size&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;window-inherit-font-size&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;window-height&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 33&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;window-width&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 130&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;mouse-hide-while-typing&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;shell-integration&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; zsh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;clipboard-paste-protection&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# macos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;## nix handles updates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;auto-update&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; off&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;macos-titlebar-style&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; native&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;macos-option-as-alt&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;quit-after-last-window-closed&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;keybind&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; shift+enter=text:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;shell-prompt&quot;&gt;Shell Prompt&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://starship.rs/?ref=blog.ktz.me&quot;&gt;Starship&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The prompt that you see (the bit that contains the filepath, username, etc) is configured using &lt;a href=&quot;https://starship.rs/?ref=blog.ktz.me&quot;&gt;Starship&lt;/a&gt; - a minimal, blazing fast, customizable shell prompt.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-width-wide&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/Screenshot-2025-09-12-at-12.00.56.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1968&quot; height=&quot;1122&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2025/09/Screenshot-2025-09-12-at-12.00.56.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2025/09/Screenshot-2025-09-12-at-12.00.56.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2025/09/Screenshot-2025-09-12-at-12.00.56.png 1600w&quot; sizes=&quot;(min-width: 1200px) 1200px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;p&gt;The configuration I use hangs out in my &lt;a href=&quot;https://github.com/ironicbadger/nix-config/blob/main/home/starship/starship.toml?ref=blog.ktz.me&quot;&gt;nix-config git repo&lt;/a&gt;. I use nix and nix-darwin to apply this configuration automatically.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-bookmark-card&quot;&gt;&lt;a class=&quot;kg-bookmark-container&quot; href=&quot;https://github.com/ironicbadger/nix-config/blob/main/home/starship/starship.toml?ref=blog.ktz.me&quot;&gt;&lt;div class=&quot;kg-bookmark-content&quot;&gt;&lt;div class=&quot;kg-bookmark-title&quot;&gt;nix-config/home/starship/starship.toml at main · ironicbadger/nix-config&lt;/div&gt;&lt;div class=&quot;kg-bookmark-description&quot;&gt;Contribute to ironicbadger/nix-config development by creating an account on GitHub.&lt;/div&gt;&lt;div class=&quot;kg-bookmark-metadata&quot;&gt;&lt;img class=&quot;kg-bookmark-icon&quot; src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/icon/pinned-octocat-093da3e6fa40-3.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;span class=&quot;kg-bookmark-author&quot;&gt;GitHub&lt;/span&gt;&lt;span class=&quot;kg-bookmark-publisher&quot;&gt;ironicbadger&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;kg-bookmark-thumbnail&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/thumbnail/nix-config-1&quot; alt=&quot;&quot; onerror=&quot;this.style.display = &apos;none&apos;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;h2 id=&quot;editor&quot;&gt;Editor&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;VSCode - the editor that in the darkness bound them&lt;/li&gt;
&lt;li&gt;Neovim - I am still experimenting with neovim but you can find my configuration &lt;a href=&quot;https://github.com/ironicbadger/neovim-config?ref=blog.ktz.me&quot;&gt;on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The VSCode theme shown below is &lt;code&gt;Bearded Theme Monokai Stone&lt;/code&gt;. For right now I am using the default icons but in the past the Bearded Icons pack may have been shown too.&lt;/p&gt;
&lt;figure class=&quot;kg-card kg-image-card kg-width-wide&quot;&gt;&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/Screenshot-2025-09-12-at-12.03.51.png&quot; class=&quot;kg-image&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1390&quot; srcset=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w600/2025/09/Screenshot-2025-09-12-at-12.03.51.png 600w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1000/2025/09/Screenshot-2025-09-12-at-12.03.51.png 1000w, https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/size/w1600/2025/09/Screenshot-2025-09-12-at-12.03.51.png 1600w&quot; sizes=&quot;(min-width: 1200px) 1200px&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;other-useful-tools&quot;&gt;Other useful tools&lt;/h2&gt;
&lt;p&gt;In no particular order a list of other tools I use and enjoy on macOS in particular are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bentoboxapp.com/?ref=blog.ktz.me&quot;&gt;BentoBox&lt;/a&gt; - Window management app&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://snippety.app/?ref=blog.ktz.me&quot;&gt;Snippety&lt;/a&gt; - Text expansion&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.raycast.com/?ref=blog.ktz.me&quot;&gt;Raycast&lt;/a&gt; - Spotlight replacement&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://icemenubar.app/?ref=blog.ktz.me&quot;&gt;Ice&lt;/a&gt; - makes app “systray” icons on macOS bearable (especially with a notch)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bjango.com/mac/istatmenus/?ref=blog.ktz.me&quot;&gt;iStat Menus&lt;/a&gt; - Shows me what’s going at a glance&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hammerflow.dev/?ref=blog.ktz.me&quot;&gt;Hammerflow&lt;/a&gt; (and Hammerspoon) - Keyboard driven task navigation&lt;/li&gt;
&lt;/ul&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/09/Screenshot-2025-09-12-at-12.07.30.png" medium="image"/><category>technical</category></item><item><title>Proxmox 9 broke my docker containers</title><link>https://blog.ktz.me/proxmox-9-broke-my-docker-containers/</link><guid isPermaLink="false">68a27e2d1d015e0001e2a694</guid><description>A simple but effective way to &quot;fix&quot; things is to disable apparmor, here&apos;s how.</description><pubDate>Mon, 18 Aug 2025 01:35:18 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/08/IMG_3451.jpg&quot; alt=&quot;Proxmox 9 broke my docker containers&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.proxmox.com/en/about/company-details/press-releases/proxmox-virtual-environment-9-0?ref=blog.ktz.me&quot;&gt;Proxmox 9&lt;/a&gt; is out 🎉 with a whole host of wonderful upgrades and improvements.&lt;/p&gt;
&lt;p&gt;Unfortunately, it prevents any of the docker containers I had running on the host itself from starting as Proxmox 9 ships with apparmor enabled but no default docker apparmor profile.&lt;/p&gt;
&lt;p&gt;All containers that need access to the docker socket (&lt;em&gt;traefik&lt;/em&gt;), or use an s6 overlay (any &lt;a href=&quot;https://linuxserver.io/?ref=blog.ktz.me&quot;&gt;Linuxserver.io&lt;/a&gt; image and 1000s more) are affected so I am sure this will trip up a lot of you over the coming weeks. Good luck!&lt;/p&gt;
&lt;p&gt;After spending about an hour attempting to get a valid, but permissive, apparmor profile working I just needed a quick solution to get things up and running whilst I fixed the problem “properly”.&lt;/p&gt;
&lt;p&gt;The workaround came via a very old &lt;a href=&quot;https://github.com/moby/moby/issues/41553?ref=blog.ktz.me#issuecomment-2056845244&quot;&gt;GitHub issue&lt;/a&gt; showing how to disable apparmor for the entire docker daemon.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ systemctl edit docker&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;[Service]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;Environment&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;container&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;setmeandforgetme&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you’ve edited the file, perform &lt;code&gt;systemctl daemon-reload&lt;/code&gt; followed by &lt;code&gt;systemctl restart docker&lt;/code&gt; and you should be up and running.&lt;/p&gt;
&lt;p&gt;Hilariously, this works by setting the environment variable value for &lt;code&gt;container&lt;/code&gt; to literally &lt;em&gt;any string&lt;/em&gt;, and thus disabling apparmor. A frustrating concatenation of issues led me here for sure.&lt;/p&gt;
&lt;p&gt;Keep an eye out for a more secure, betterer, more permanent solution but for tonight this will do nicely.&lt;/p&gt;
&lt;h1 id=&quot;why-make-it-harder-for-your-users&quot;&gt;Why make it harder for your users?&lt;/h1&gt;
&lt;p&gt;Apparmor is kind of like SELinux. It has rules that says which things can talk to which other things, what can create network sockets, and so on. It is a very useful security feature in production environments and significantly reduces attack vectors.&lt;/p&gt;
&lt;p&gt;HOWEVER, my situation is in a homelab and to be honest I don’t want or need that extra complexity.&lt;/p&gt;
&lt;p&gt;The Proxmox developers have gone on record to say that you should not run docker containers directly on the host, but run them in a VM instead. Why? It’s my system, I will &lt;a href=&quot;https://www.engadget.com/2010-06-24-apple-responds-over-iphone-4-reception-issues-youre-holding-th.html?ref=blog.ktz.me&quot;&gt;&lt;em&gt;hold it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;however I damn well want&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Seriously, Proxmox is &lt;em&gt;such&lt;/em&gt; a fantastic project but why make your product harder to use for the vast majority of folks running containers. Docker is the overwhelming leader in this space &lt;em&gt;not&lt;/em&gt; LXCs.&lt;/p&gt;
&lt;p&gt;Running containers on the host for me has several key advantages including (but not limited to):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;not needing to fart around with PCI passthrough for GPU accelerated workloads (video transcoding, LLMs via an Nvidia GPU)&lt;/li&gt;
&lt;li&gt;being able to share those hardware resources across multiple containers in a single, easy abstraction (docker)&lt;/li&gt;
&lt;li&gt;simplicity of adminstration&lt;/li&gt;
&lt;li&gt;simple and direct access to host storage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Users like the one in &lt;a href=&quot;https://forum.proxmox.com/threads/tip-if-you-would-like-to-host-docker-on-a-pve-9-host.169747/?ref=blog.ktz.me&quot;&gt;this thread&lt;/a&gt; make for a really bad smell around a project. And whilst &lt;a href=&quot;https://forum.proxmox.com/threads/docker-containers-fail-to-start-on-proxmox-9-debian-13-host-worked-fine-on-proxmox-8.169508/?ref=blog.ktz.me#post-790284&quot;&gt;this thread&lt;/a&gt; led me to my ultimate workaround tonight, it’s frustrating to see folks defending what is ultimately a user hostile decision.&lt;/p&gt;
&lt;p&gt;Over the years I have found tremendous benefits from simplifying the stack wherever I can in my homelab. I do enough tinkering and complex stuff at &lt;code&gt;$dayjob&lt;/code&gt; and Proxmox provides the perfect blend of ZFS, container support, a useful webUI, stable releases, and flexibility because it’s &lt;em&gt;just Linux&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Stop making me feel bad about using my computer the way I want to. Just be happy we are here, using a tool to get a job done in the way we best see fit.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/08/IMG_3451.jpg" medium="image"/><category>technical</category><category>proxmox</category></item><item><title>What if..?</title><link>https://blog.ktz.me/what-if/</link><guid isPermaLink="false">6855a12a8165f10001b0f860</guid><description>I have a 4 hour flight next week, grab the Top Gear specials and send them to my iPad</description><pubDate>Fri, 20 Jun 2025 18:07:07 GMT</pubDate><content:encoded>&lt;img src=&quot;https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/06/140A6530-1798x1080.jpg&quot; alt=&quot;What if..?&quot;&gt;&lt;p&gt;“I have a 4 hour flight next week, grab the Top Gear specials and send them to my iPad”. Or a step better, an LLM looks ahead to your calendar and &lt;em&gt;just figures it out&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As far as I know nothing exists today with enough context into each of the elements required to make this relatively simple idea work.&lt;/p&gt;
&lt;p&gt;Imagine if the LLM involved here knew the iPad you were talking about, the current free space, it’s resolution, and any other constraints and &lt;em&gt;just handled the complexities -&lt;/em&gt; including offline transfer and encoding of the files to a suitable file size for the target device? Synced watch status and all the rest of it via Jellyfin would be neat.&lt;/p&gt;
&lt;p&gt;After all… how hard can it be?&lt;/p&gt;
&lt;p&gt;I suppose you could string together a bunch of this stuff together with n8n and ffmpeg perhaps. Anywho, I could see this being the future of software both commercially and for self-hosters.&lt;/p&gt;</content:encoded><dc:creator>Alex Kretzschmar</dc:creator><media:content url="https://pub-430e0c9ecb66464fa6999cd23a749d13.r2.dev/content/images/2025/06/140A6530-1798x1080.jpg" medium="image"/><category>technical</category></item></channel></rss>