<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl" media="all"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Roastidio.us Tagged with linux</title>
<link>https://roastidio.us/tag/2428</link>
<atom:link href="https://roastidio.us/tagged_with/linux" rel="self" type="application/rss+xml"></atom:link>
<description>Roastidio.us Tagged with linux</description>
<item>
<title>Homebrew Release: Warnel Chawpiovs v1.5.0 (PC, Nintendo Switch, Android), adds 9 new heroes and significant performance improvements</title>
<link>https://wololo.net/2026/07/03/homebrew-release-warnel-chawpiovs-v1-5-0-pc-nintendo-switch-android-adds-9-new-heroes-and-significant-performance-improvements/</link>
<guid isPermaLink="false">F-B7gTm2olVfisbulX4pEZaT5PQxPVtG_qtx1A==</guid>
<pubDate>Fri, 17 Jul 2026 17:09:28 +0000</pubDate>
<description>I’ve just released version 1.5.0 of “Warnel Chawpiovs”, a homebrew game for PC (Windows, Linux, MacOS versions are now available), Nintendo Switch, and Android. This new release fixes some significant rendering and performance issues.... The post Homebrew Release: Warnel Chawpiovs v1.5.0 (PC, Nintendo Switch, Android), adds 9 new heroes and significant performance improvements appeared first on Wololo.net.</description>
<content:encoded>&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/characters_scenarios.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;I’ve just released version 1.5.0 of “Warnel Chawpiovs”, a homebrew game for PC (Windows, Linux, MacOS versions are now available), Nintendo Switch, and Android.&lt;/p&gt;&lt;p&gt;This new release fixes some significant rendering and performance issues. Specifically, there was a rendering problem in previous releases which made the game look very pixelated on any screen that wasn’t exactly 1920×1080. This should now be fixed, and the fix comes with some performance improvements in game.&lt;/p&gt;&lt;p&gt;Version 1.5.0 also brings 9 new heroes: Nebula, Gamora, Drax, Wolverine, Venom, Nightcrawler, Scarlet witch, Phoenix, and Valkyrie. I’ve tried to focus on heroes with a default “Justice” deck, as it has come to my attention that the number of Justice cards available in the Deck Editor was lagging a bit behind Aggression, Leadership and Protection.&lt;/p&gt;&lt;p&gt;(&lt;strong&gt;By the way, if you’re using and enjoying Warnel Chawpiovs, please do me a favor and spread the word, to friends or on social networks&lt;/strong&gt;. Having a growing number of users helps me staying motivated to add more cards and features!)&lt;/p&gt;&lt;p&gt;Overall, the game now supports 36 heroes and 28 scenarios, which I estimate represents roughly 40% of all the cards in the original game (excluding campaigns)&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;This is a fan-created work and is not affiliated with, endorsed by, or sponsored by Fantasy Flight Games. All characters, settings, and related elements are the property of their respective owners.&lt;/strong&gt;&lt;/p&gt;&lt;h2&gt;What is Warnel Chawpiovs ?&lt;/h2&gt;&lt;p&gt;Warnel Chawpiovs, aka WC, is a homebrew game for multiple platforms (included, but not limited to, Nintendo Switch, Android and Windows), based on the popular cooperative board game Marvel Champions. WC lets you play the popular card game with full rules enforcement. The game does the heavy lifting of handling all the rules, so you only have to focus on your strategy.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/06/sabretooth_kelly.jpg?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/06/sabretooth_kelly.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It also includes a full fledged deck editor (which, among other things, can import/export decks from popular fansite &lt;a href=&quot;https://marvelcdb.com&quot;&gt;marvelcdb.com&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/05/marvel_champions-1_3_0_deck_editor_3.jpg?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/05/marvel_champions-1_3_0_deck_editor_3.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Please note that Warnel Chawpiovs doesn’t hold your hand. Although it automates all of the gameplay, you will still need a basic understanding of the original rules to know what’s going on. The rules can be found here if you’re interested: &lt;a href=&quot;https://www.fantasyflightgames.com/en/products/marvel-champions-the-card-game/&quot;&gt;https://www.fantasyflightgames.com/en/products/marvel-champions-the-card-game/&lt;/a&gt;  (scroll down to the support/rules section and download “&lt;a href=&quot;https://images-cdn.fantasyflightgames.com/filer_public/ab/be/abbef836-d5ef-4241-b2bd-1062df73f367/mvc01_learn_to_play_eng-compressed.pdf&quot;&gt;Learn to play&lt;/a&gt;“)&lt;/p&gt;&lt;p&gt;You can play on your own with one or multiple heroes, and there’s also a multiplayer mode, although I need to emphasize once again, multiplayer doesn’t exactly work*&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/05/marvel_champions-1_3_0_groot_vs_drang_5.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;Warnel Chawpiovs – What’s new in 1.5.0&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Added 9 new heroes and their associated cards: Nebula, Gamora, Drax, Wolverine, Venom, Nightcrawler, Scarlet witch, Phoenix, and Valkyrie. This represents roughly 300 new cards.&lt;/li&gt;&lt;li&gt;Vastly improved the rendering on most devices. If the game looked heavily “pixelated” in previous releases to you, you might want to give this new version a try. Depending on your case, the game possibly went from “text is unreadable and images have an aliasing problem” to “this now looks ok”&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/before_after.png?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/before_after.png?resize=696%2C937&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Performance improvements ingame, which now should make the 4 heroes experience in particular much more playable.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;1.5.0 Development notes and anecdotes&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: I thought 1.4.x was doing ok in terms of performance even with 4 heroes, but after trying a few games, it was clear that more effort was required on that front.&lt;/p&gt;&lt;p&gt;Warnel Champions uses the concept of “Alterants”  (inherited from the Card Framework I’m using) which regularly computes any modification that a card might receive from another on the board (for example, a hypothetical card that says “your hero gets +1 ATK”). Making sure this information is constantly up to date but also not too computation-intensive is one of the main problems I’ve been trying to solve. I think I’ve done a good job now at avoiding unnecessary calls to this heavy function. It’s still not perfect in a 4 player game, but much better than in any previous release, as far as I can tell.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Heroes&lt;/strong&gt;: I’m bringing 9 new heroes to this release. This is a new record, but I’m “cheating” a bit because I’m not bringing any new villains. Villains and encounters have been significantly more difficult to develop and test than hero cards, and I think the priority right now should be to support as many player cards as possible so that people can build any deck they want. Some of the new heroes are really fun. Nebula and Gamora are an interesting combination when playing two heroes, thanks to Nebula’s Nemesis treachery which literally forces your friend to attack you.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/22031.png?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/22031.png?resize=300%2C419&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Scarlet Witch was probably the one that demanded the most additional work in the game engine, with her ability to modify boost icon counts at the last minute. To be perfectly honest, the way I implemented it isn’t perfect, and there are several cards in the game that will slightly break when Scarlet Witch interacts with them. Hopefully people won’t run into the issue too often, and eventually I might be able to fix that. In the meantime, her ability to alter a lot of boost icons makes her very powerful and quite fun to play.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/15001a.png?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/15001a.png?resize=300%2C419&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/15004.png?ssl=1&quot;&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/07/15004.png?resize=300%2C419&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;How to install – Windows/Linux&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/01/warvel_chawpiovs_1.0.0_spider_woman.jpg?resize=1024%2C574&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Download the binaries below or on the github page:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wololo.net/downloads/index.php/download/10292&quot;&gt;Warnel Chawpiovs Download page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(alternatively &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/releases&quot;&gt;on github&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;extract anywhere on your computer, then run the binary file (Windows: WC.exe, Linux:WC.x86_64)&lt;/p&gt;&lt;h2&gt;How to install – Android&lt;/h2&gt;&lt;p&gt;Download the apk below or on the github page:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wololo.net/downloads/index.php/download/10292&quot;&gt;Warnel Chawpiovs Download page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(alternatively &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/releases&quot;&gt;on github&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;Copy the apk to your phone then install it with your phone’s file manager. You will need to enable “unknown sources” in your phone settings in order to install the APK.&lt;/p&gt;&lt;p&gt;Once you start the game it will need to download resources so it is recommended that your first launch is not on an expensive data plan &lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png&quot; alt=&quot;🙂&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;How to install – Nintendo Switch&lt;/h2&gt;&lt;p&gt;You will need a hacked Nintendo Switch to run this game.&lt;/p&gt;&lt;p&gt;Download the binaries below or on the github page:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wololo.net/downloads/index.php/download/10292&quot;&gt;Warnel Chawpiovs Download page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(alternatively &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/releases&quot;&gt;on github&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;extract the WC folder inside your switch folder on your SD card.&lt;/p&gt;&lt;p&gt;Launch the homebrew Menu in “full speed” mode (not in applet mode). This is done by pressing the Right Should button (R) while launching a cartridge game.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2025/12/warnel_chawpiovs_hbmenu.jpg?resize=1024%2C431&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;From there, you can run the game&lt;/p&gt;&lt;h2&gt;How to install – Mac OS&lt;/h2&gt;&lt;p&gt;Download the binaries below or on the github page:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wololo.net/downloads/index.php/download/10292&quot;&gt;Warnel Chawpiovs Download page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(alternatively &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/releases&quot;&gt;on github&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;The Mac OS app isn’t officially signed, so in order to run it you can ctrl + click and select “open”&lt;/p&gt;&lt;h2&gt;Running your First Game&lt;/h2&gt;&lt;p&gt;The game will attempt to download any missing picture for new cards, as soon as you run it. This happens in the background and you can play while this happens. Again, that step is not needed if you have the appropriate “*.zip” resource files.&lt;/p&gt;&lt;p&gt;Once you’re in the game select “Sivgle Player”, then choose one hero and one villain, then click on launch.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/01/warvel_chawpiovs_1.0.0_adventure_mode.jpg?resize=1024%2C575&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Note: On your very first run, the game will only let you select one hero and one villain. This is intentional, as the game’s “adventure mode” requires you to win games in order to unlock more heroes and scenarios. If you don’t like this you can deactivate it in the options/gameplay menu, this will unlock all content.&lt;/p&gt;&lt;p&gt;Check the Videos below for examples of gameplay&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;Status of the Switch port&lt;/h2&gt;&lt;p&gt;The Switch port is… slow. You might want to &lt;a href=&quot;https://github.com/retronx-team/sys-clk&quot;&gt;overclock your console&lt;/a&gt; when you play the game. I know it’s not ideal, but it makes the gameplay much more comfortable.&lt;/p&gt;&lt;p&gt;I would not recommend playing with more than one hero at the moment on Nintendo Switch, if only for performance reasons&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/02/wc_1.1.0_2_player_game_2.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;Troubleshooting, bug reports, etc…&lt;/h2&gt;&lt;p&gt;I do not have a dedicated forum or discord in place for this game yet. You can open issues on the &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/issues&quot;&gt;github project&lt;/a&gt;, or contact me by email (wagic.the.homebrew at gmail), but please understand that I might dismiss or ignore most of those depending on free time and interest.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2025/12/2025123109054900-4E551BEEBAD303591E38565E64373519.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;Known issues&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Multiplayer should basically be considered broken for now.&lt;/li&gt;&lt;li&gt;Loading/Saving games is hit and miss depending on the hero/villain&lt;/li&gt;&lt;li&gt;Switch port is slow. You might want to &lt;a href=&quot;https://github.com/retronx-team/sys-clk&quot;&gt;overclock your console&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The Mac port should be considered unsupported. I do not own any Apple products, which makes it impossible for me to verify (let alone debug) anything on that version.&lt;/li&gt;&lt;li&gt;There are still lots of issues with specific cards, but feel free to &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/issues&quot;&gt;report issues you find on the github&lt;/a&gt;&lt;ul&gt;&lt;li&gt;In particular multiple cards behave strangely when playing with more than one hero. This isn’t intentional so feel free to report those&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/02/wc_1.1.0_2_player_game_3.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;Want more details?&lt;/h2&gt;&lt;p&gt;check the &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs&quot;&gt;Readme on github&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;What’s next:&lt;/h2&gt;&lt;p&gt;There is still lots of work to do with this game. I am currently focusing on adding more cards to enjoy with a solo hero.&lt;/p&gt;&lt;p&gt;If by any miracle you are looking at my code and can help, in particular with multiplayer issues, please submit a &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs&quot;&gt;PR on github&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/wololo.net/wagic/wp-content/uploads/2026/01/warvel_chawpiovs_1.0.0_hero_unlock.jpg?resize=1024%2C576&amp;amp;ssl=1&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h2&gt;Download&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wololo.net/downloads/index.php/download/10292&quot;&gt;Download page&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Or on the &lt;a href=&quot;https://github.com/frwololo/warnel-chawpiovs/releases&quot;&gt;project’s github page&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;*  If you badly want to play Marvel Champions with friends online, the &lt;a href=&quot;https://irefrixs.itch.io/marvel-lcg&quot;&gt;Marvel champions digital edition&lt;/a&gt;, another unofficial fan game, does a great job at it.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;The post &lt;a href=&quot;https://wololo.net/2026/07/03/homebrew-release-warnel-chawpiovs-v1-5-0-pc-nintendo-switch-android-adds-9-new-heroes-and-significant-performance-improvements/&quot;&gt;Homebrew Release: Warnel Chawpiovs v1.5.0 (PC, Nintendo Switch, Android), adds 9 new heroes and significant performance improvements&lt;/a&gt; appeared first on &lt;a href=&quot;https://wololo.net&quot;&gt;Wololo.net&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Download Debian ISO: With Easy Installation Guide</title>
<link>https://techrechard.com/download-debian-iso/</link>
<guid isPermaLink="false">dgBRn_W39J76v70eZeBrzwPvvpeMeE8KC4g0Dw==</guid>
<pubDate>Fri, 17 Jul 2026 13:48:25 +0000</pubDate>
<description>The world of Linux offers a vast landscape of distributions, but few are as respected, stable, and foundational as Debian. For many users, the journey into this powerful operating system begins with a single file: the Debian ISO. This file is more than just an installer; it’s a gateway to a free, open-source computing environment renowned [...]</description>
<content:encoded>&lt;p&gt;The world of &lt;a href=&quot;https://techrechard.com/category/linux/&quot;&gt;Linux &lt;/a&gt;offers a vast landscape of distributions, but few are as respected, stable, and foundational as Debian. For many users, the journey into this powerful operating system begins with a single file: the &lt;strong&gt;Debian ISO&lt;/strong&gt;. This file is more than just an installer; it’s a gateway to a free, open-source computing environment renowned for its robustness and commitment to software freedom.&lt;/p&gt;&lt;p&gt;Whether you’re a seasoned system administrator, a developer, or a curious newcomer, understanding how to obtain and use a Debian ISO properly is the first critical step. This guide will walk you through everything you need to know to get Debian up and running on your machine.&lt;/p&gt;&lt;h2&gt;What Exactly is a Debian ISO?&lt;/h2&gt;&lt;p&gt;An ISO image (often called an “ISO”) is a complete archive of everything on an optical disc, such as a CD or DVD, stored in a single file. In the context of Debian, the Debian ISO is an all-in-one file containing the entire operating system and its installer. You can use this file to create bootable installation media—typically a USB drive or a DVD—then use it to install Debian on your computer. It’s the digital blueprint for your new operating system.&lt;/p&gt;&lt;h2&gt;Before You Download: Key Considerations&lt;/h2&gt;&lt;p&gt;Before you click that download link, take a moment to answer a few questions to ensure you get the right version and have a smooth experience.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Choose Your Architecture:&lt;/strong&gt; Modern computers are most likely &lt;code&gt;amd64&lt;/code&gt; (also known as x86-64). This covers most Intel and AMD processors. Other architectures like &lt;code&gt;arm64&lt;/code&gt; (for newer Raspberry Pis, servers, and ARM-based devices), &lt;code&gt;armhf&lt;/code&gt; (for older ARM devices), &lt;code&gt;ppc64el&lt;/code&gt; (POWER8 and POWER9), &lt;code&gt;riscv64&lt;/code&gt;, and &lt;code&gt;s390x&lt;/code&gt; (mainframes) serve specific hardware.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Desktop Environment vs. Network Install:&lt;/strong&gt; Debian offers different types of ISOs.
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Live Images:&lt;/strong&gt; These allow you to try Debian without installing it. You can boot directly from the USB drive and, if you like, launch the installer from the desktop. These are great for testing hardware compatibility.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Full Installation Images:&lt;/strong&gt; These are larger (~4 GB DVD ISOs) that contain a vast collection of software packages, allowing you to install without an internet connection.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Network Install Images:&lt;/strong&gt; This is the recommended method for most users. This is a very small ISO (~500 MB) that contains only the essential tools to start the installation. It then downloads all the latest packages directly from Debian’s servers during the install process, ensuring you get the most up-to-date software.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Check Your Hardware:&lt;/strong&gt; Ensure your computer meets the minimum system requirements, which are quite modest by today’s standards. For a standard desktop installation, 2 GB of RAM and 10 GB of disk space are good starting points.&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;How to Download Debian ISO&lt;/h2&gt;&lt;p&gt;You can obtain a Debian ISO image in several ways, each with its own advantages.&lt;/p&gt;&lt;h3&gt;Method 1: Direct HTTP/FTP Download&lt;/h3&gt;&lt;p&gt;The most straightforward method is to download the ISO directly from one of Debian’s many official mirrors worldwide. This is simple, but it relies on the stability of your internet connection, especially for the larger DVD images.&lt;/p&gt;&lt;h3&gt;Network Install ISO&lt;/h3&gt;&lt;p&gt;To use this, you will need a machine with an Internet connection.&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Architecture&lt;/th&gt;&lt;th&gt;Image Type&lt;/th&gt;&lt;th&gt;Download Link (HTTP)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;amd64&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.6.0-amd64-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;arm64&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.6.0-arm64-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;armhf&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/armhf/iso-cd/debian-13.6.0-armhf-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ppc64el&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/ppc64el/iso-cd/debian-13.6.0-ppc64el-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;riscv64&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/riscv64/iso-cd/debian-13.6.0-riscv64-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;s390x&lt;/td&gt;&lt;td&gt;Netinst&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/s390x/iso-cd/debian-13.6.0-s390x-netinst.iso&quot;&gt;Download&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;pre&gt;&lt;strong&gt;amd64&lt;/strong&gt; is for standard 64-bit PCs and servers. &lt;br/&gt;&lt;strong&gt;arm64&lt;/strong&gt; is for modern, efficient devices like phones and newer single-board computers. &lt;br/&gt;&lt;strong&gt;armhf&lt;/strong&gt; is for older 32-bit ARM devices like the Raspberry Pi 2. &lt;br/&gt;&lt;strong&gt;ppc64el&lt;/strong&gt; is for IBM POWER servers. &lt;br/&gt;&lt;strong&gt;riscv64&lt;/strong&gt; is an open-source architecture for new embedded and experimental hardware. &lt;br/&gt;&lt;strong&gt;s390x&lt;/strong&gt; is for IBM mainframe computers.&lt;/pre&gt;&lt;h3&gt;&lt;strong&gt;Complete Installation ISO&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;A larger&lt;span&gt;, &lt;strong&gt;complete installation image&lt;/strong&gt; that includes&lt;/span&gt; packages for all desktop environments, making it easier to install machines without an Internet connection.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/iso-dvd/debian-13.6.0-amd64-DVD-1.iso&quot;&gt;Download &lt;/a&gt;| &lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/bt-dvd/debian-13.6.0-amd64-DVD-1.iso.torrent&quot;&gt;Torrent&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;Live Install ISO&lt;/h3&gt;&lt;p&gt;You can try Debian by booting a live system from a CD, DVD, or USB key without installing any files to the computer. Only available for 64-bit PC&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Desktop Environments&lt;/th&gt;&lt;th&gt;Download Links&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Cinnamon&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-cinnamon.iso&quot;&gt;debian-live-13.6.0-amd64-cinnamon.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Debian Jr.&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-debian-junior.iso&quot;&gt;debian-live-13.6.0-amd64-debian-junior.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GNOME&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-gnome.iso&quot;&gt;debian-live-13.6.0-amd64-gnome.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;KDE &lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-kde.iso&quot;&gt;debian-live-13.6.0-amd64-kde.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LXDE&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-lxde.iso&quot;&gt;debian-live-13.6.0-amd64-lxde.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LXQt&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-lxqt.iso&quot;&gt;debian-live-13.6.0-amd64-lxqt.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MATE&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-mate.iso&quot;&gt;debian-live-13.6.0-amd64-mate.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Standard&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-standard.iso&quot;&gt;debian-live-13.6.0-amd64-standard.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Xfce&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.6.0-amd64-xfce.iso&quot;&gt;debian-live-13.6.0-amd64-xfce.iso&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h3&gt;Method 2: Using a Torrent Client (Recommended)&lt;/h3&gt;&lt;p&gt;For larger files, such as the Complete &lt;strong&gt;Debian ISO&lt;/strong&gt;, using the provided &lt;strong&gt;Debian ISO&lt;/strong&gt;&lt;strong&gt;torrent &lt;/strong&gt;is highly recommended. This method is often faster and more reliable because your client downloads parts of the file from multiple sources simultaneously. It also reduces the load on Debian’s main servers and helps you become part of the distribution network, ensuring the &lt;strong&gt;Debian ISO &lt;/strong&gt;remains available to others.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Install a torrent client like &lt;code&gt;qBittorrent&lt;/code&gt;, &lt;code&gt;Transmission&lt;/code&gt;, or &lt;code&gt;Deluge&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Click the “&lt;strong&gt;Debian ISO Torrent File&lt;/strong&gt;” link from the table above to download the &lt;code&gt;.torrent&lt;/code&gt; file, then open it with your client.&lt;/li&gt;&lt;/ol&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Architecture&lt;/th&gt;&lt;th&gt;Torrent Download Link&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;13.5.0 AMD 64-bit&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/bt-cd/debian-13.6.0-amd64-netinst.iso.torrent&quot;&gt;debian-13.6.0-amd64-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 AMD 64-bit – Education&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/bt-cd/debian-edu-13.6.0-amd64-netinst.iso.torrent&quot;&gt;debian-edu-13.6.0-amd64-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 AMD 64-bit – MAC&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/amd64/bt-cd/debian-mac-13.6.0-amd64-netinst.iso.torrent&quot;&gt;debian-mac-13.6.0-amd64-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 ARM 64-bit&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/arm64/bt-cd/debian-13.6.0-arm64-netinst.iso.torrent&quot;&gt;debian-13.6.0-arm64-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 ARMHF&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/armhf/bt-cd/debian-13.6.0-armhf-netinst.iso.torrent&quot;&gt;debian-13.6.0-armhf-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 PPC64EL&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/ppc64el/bt-cd/debian-13.6.0-ppc64el-netinst.iso.torrent&quot;&gt;debian-13.6.0-ppc64el-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 RISCV64&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/riscv64/bt-cd/debian-13.6.0-riscv64-netinst.iso.torrent&quot;&gt;debian-13.6.0-riscv64-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13.5.0 S390X&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/s390x/bt-cd/debian-13.6.0-s390x-netinst.iso.torrent&quot;&gt;debian-13.6.0-s390x-netinst.iso.torrent&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2&gt;Verifying Your Debian ISO Download&lt;/h2&gt;&lt;p&gt;This is a critical step for security and integrity. It ensures that the file you downloaded is authentic and hasn’t been corrupted during transfer or tampered with.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Download the Checksum Files:&lt;/strong&gt; Next to the ISO links on the official Debian page, you will find files like &lt;code&gt;SHA256SUMS&lt;/code&gt; and &lt;code&gt;SHA256SUMS.sign&lt;/code&gt;. Download these.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Generate Your ISO’s Checksum:&lt;/strong&gt; On Linux or macOS, open a terminal and navigate to the folder containing your downloaded ISO. Type the following command. On Windows, you can use a tool like &lt;code&gt;certutil&lt;/code&gt; in Command Prompt or a GUI tool like &lt;code&gt;HashCheck&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;sha256sum debian-13.5.0-amd64-netinst.iso&lt;/pre&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Compare the Checksums:&lt;/strong&gt; Compare the long string of characters generated by the command above with the one listed for your specific ISO file in the &lt;code&gt;SHA256SUMS&lt;/code&gt; file. They must match exactly.&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Creating a Bootable USB Drive&lt;/h2&gt;&lt;p&gt;With a verified &lt;strong&gt;Debian ISO&lt;/strong&gt; in hand, you need to put it on a USB drive (at least 4 GB for netinst, and 8 GB or more for live images).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;On Windows:&lt;/strong&gt; Use tools like &lt;strong&gt;&lt;a href=&quot;https://rufus.ie/en/&quot;&gt;Rufus&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href=&quot;https://www.ventoy.net/en/index.html&quot;&gt;Ventoy&lt;/a&gt;&lt;/strong&gt;. Rufus is straightforward: select your USB drive, choose the downloaded ISO, and click “Start.”&lt;/li&gt;&lt;li&gt;&lt;strong&gt;On Linux:&lt;/strong&gt; Use the &lt;code&gt;dd&lt;/code&gt; command or a graphical tool like &lt;a href=&quot;https://etcher.balena.io/&quot;&gt;&lt;strong&gt;BalenaEtcher&lt;/strong&gt; &lt;/a&gt;or &lt;strong&gt;Startup Disk Creator&lt;/strong&gt;. Be extremely careful with the &lt;code&gt;dd&lt;/code&gt; command, as selecting the wrong drive can erase your system.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;sudo dd if=path/to/debian.iso of=/dev/sdX bs=4M status=progress oflag=sync&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;(Replace &lt;code&gt;/dev/sdX&lt;/code&gt; with your actual USB device, e.g., &lt;code&gt;/dev/sdb&lt;/code&gt;).&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Booting and Installing&lt;/h2&gt;&lt;p&gt;Insert the USB drive, restart your computer, and enter your BIOS/UEFI setup (usually by pressing F2, Delete, or F12 during boot). Change the boot order to prioritize your USB drive. Save and exit. The system will boot into the Debian installer or live environment, where you can begin your installation journey.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Downloading the correct &lt;strong&gt;Debian ISO&lt;/strong&gt; is the fundamental and most important step in embracing one of the most stable and versatile operating systems available. By carefully selecting the right architecture and image type for your needs, opting for the efficient torrent download method, and rigorously verifying the file’s integrity, you lay a solid foundation for a successful installation. &lt;/p&gt;&lt;p&gt;The process, while detailed, ensures security and reliability—values at the very core of the Debian project. With your bootable USB drive ready, you are now prepared to experience the power, stability, and unparalleled freedom that Debian has offered to millions of users worldwide for decades. Welcome to the community.&lt;/p&gt;&lt;p&gt;For more Linux guides, &lt;a href=&quot;https://techrechard.com/category/linux/&quot;&gt;visit here&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Igalia and Wind River Collaborate to Deliver Production-Ready Web Runtime for Embedded Linux Devices | Igalia</title>
<link>https://www.igalia.com/2026/07/06/Igalia-and-Wind-River-Collaborate-to-Deliver-Production-Ready-Web-Runtime-for-Embedded-Linux-Devices.html</link>
<enclosure type="image/jpeg" length="0" url="https://www.igalia.com/assets/i/logo200x200Margin-og.png"></enclosure>
<guid isPermaLink="false">2zfNjhODkSA6wYKIIPo8gGPeVBqnr5Q9phUyiw==</guid>
<pubDate>Fri, 17 Jul 2026 12:55:42 +0000</pubDate>
<description>Igalia is an open source consulting firm specialised in the development of innovative projects and solutions. Our engineers have expertise in a wide range of technological areas, including browsers and client-side web technologies, graphics pipeline, compilers and virtual machines. We have the most WPE, WebKit, Chromium/Blink and Firefox expertise found in the consulting business, including many reviewers and committers. Igalia designs, develops, customises and optimises GNU/Linux-based solut...</description>
<content:encoded>&lt;p&gt;Igalia, an open source engineering consulting firm with over 25 years of experience in Linux-based systems and Web engine development, is pleased to announce &lt;a href=&quot;https://www.windriver.com/resource/enabling-web-based-user-experiences-for-embedded-linux-systems&quot;&gt;a collaboration&lt;/a&gt; under the umbrella of the &lt;a href=&quot;https://www.yoctoproject.org&quot;&gt;Yocto Project&lt;/a&gt; with &lt;a href=&quot;https://www.windriver.com/&quot;&gt;Wind River&lt;/a&gt;, a global leader in embedded Linux platforms, to deliver a production-ready Web runtime for embedded devices.&lt;/p&gt;&lt;p&gt;The joint solution combines &lt;a href=&quot;https://wpewebkit.org&quot;&gt;WPE WebKit&lt;/a&gt;, the open source Web engine port created and maintained by Igalia specifically for embedded Linux environments, with &lt;a href=&quot;https://www.windriver.com/products/embedded/linux&quot;&gt;Wind River Linux&lt;/a&gt;, a commercially supported, Yocto-based embedded platform.  Together, the two companies provide embedded product teams with a fully integrated, standards-based Web runtime backed by direct access to upstream maintainers.&lt;/p&gt;&lt;p&gt;A critical component of the solution is &lt;a href=&quot;https://github.com/Igalia/meta-webkit&quot;&gt;the meta-webkit Yocto layer&lt;/a&gt;, maintained by Igalia since 2017. This layer contains the necessary build recipes, supports multiple Yocto versions, and provides backported security fixes. It also serves as the foundation for &lt;a href=&quot;https://docs.webkit.org/Deep%20Dive/Build/CI.html&quot;&gt;upstream WebKit’s continuous integration (CI) infrastructure&lt;/a&gt; on real hardware targets, including the popular Raspberry Pi platform. This CI infrastructure allows to identify and resolve issues before they reach downstream product teams, meaningfully reducing risks for product teams.&lt;/p&gt;&lt;p&gt;Together, &lt;a href=&quot;https://www.windriver.com/&quot;&gt;Wind River&lt;/a&gt; and Igalia provide embedded developers and product teams with:&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;A production-grade embedded Linux platform integrated with WPE WebKit&lt;/li&gt;
  &lt;li&gt;A standards-based Web runtime designed for constrained and headless devices&lt;/li&gt;
  &lt;li&gt;Direct access to upstream maintainers of WebKit and the WPE stack&lt;/li&gt;
  &lt;li&gt;A fully open source solution, minimizing dependency on proprietary frameworks&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;A Web engine provides a full application runtime that includes rendering, scripting, networking, and multimedia support, making it a compelling alternative to proprietary UI stacks. This is why modern embedded devices are increasingly adopting Web-based runtimes, including devices such as industrial human-machine interfaces, automotive systems, home appliances, smart TVs, and set-top boxes.  Igalia’s deep and broad experience with Web engines, along with our foundational focus on open source development, gives us a unique skill set to bring to projects that use Web engines and similar open technologies.&lt;/p&gt;&lt;p&gt;This collaboration between Igalia and Wind River is the latest entry in our long history of helping others meld the power of the Web with their projects to deliver truly robust solutions, creating a strong foundation for building modern, Web-based embedded applications. It allows product teams to accelerate development, reduce integration complexity, and maintain long-term control over their software stacks using open source technologies.  Embedded teams that need upstream support and long-term WebKit alignment now have a production-grade Linux platform to pair with it.&lt;/p&gt;&lt;p&gt;If you’d like to work with us, &lt;a href=&quot;https://igalia.com/contact&quot;&gt;please get in touch&lt;/a&gt; to learn more and see how we can help your project get further, faster.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Building My Own GPS Stratum-1 Time Server on a Raspberry Pi - Jack Stromberg</title>
<link>https://jackstromberg.com/2026/07/building-my-own-gps-stratum-1-time-server-with-a-live-dashboard-on-a-raspberry-pi/</link>
<guid isPermaLink="false">yM6pxqm2vcUYxYzk-5QS1gqLmYEhiJsN_aUtjQ==</guid>
<pubDate>Fri, 17 Jul 2026 07:05:30 +0000</pubDate>
<description>Building My Own GPS Stratum-1 Time Server on a Raspberry Pi Time silently hums away in the background, affecting everything we do today. Wake up, go to work, go to an appointment; all happen at specific times. Computers are no different, constantly logging time in logs, showing time in applications, and used for scheduling. In […]</description>
<content:encoded>&lt;h1&gt;Building My Own GPS Stratum-1 Time Server on a Raspberry Pi&lt;/h1&gt;&lt;p&gt;Time silently hums away in the background, affecting everything we do today. Wake up, go to work, go to an appointment; all happen at specific times. Computers are no different, constantly logging time in logs, showing time in applications, and used for scheduling. In general, no one really cares about time because it&amp;#39;s typically &amp;quot;accurate enough&amp;quot; for most tasks. Most computers just automatically have the correct time and are accurate down to a second or so, with most people perfectly content that it&amp;#39;s technically &lt;em&gt;approximately&lt;/em&gt; right. That being said, I&amp;#39;m neurotic and want nuclear-science-lab accuracy, knowing precisely what time it is.&lt;/p&gt;&lt;p&gt;While &lt;code&gt;pool.ntp.org&lt;/code&gt; is a fantastic source of time, why settle when you can have sub-microsecond precision? No one is going to have a good time when you&amp;#39;re technically having a bad time.&lt;/p&gt;&lt;p&gt;For this project, I wanted to see how precise time can be in my house, owning it end to end — no leaning on someone else&amp;#39;s server out on the internet. In the industry, precision time is provided by what are called stratum-1 time servers and can sometimes be thousands of dollars. Given I&amp;#39;m cheap and don&amp;#39;t have a money tree, I decided to build my own &lt;strong&gt;stratum-1 time server&lt;/strong&gt; in a relatively affordable way: a Raspberry Pi that pulls time straight off the GPS satellites overhead and serves it to everything on my LAN, no internet required.&lt;/p&gt;&lt;p&gt;Along the way the project grew a second half, which is to visualize the satellite tracking and time sync. Once I had gpsd and chrony working, I wrote a small daemon that enables a live view of the calculated time, full gpsd + chrony stats, a satellite sky view, and an interactive 3D globe showing the GNSS constellation in space.&lt;/p&gt;&lt;p&gt;This build stands on the shoulders of the classic &lt;a href=&quot;https://www.jacobdeane.com/iot/2020/building-a-gps-based-time-server/&quot;&gt;jacobdeane.com GPS time server guide&lt;/a&gt;, with two deliberate modernizations:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;chrony instead of &lt;code&gt;ntpd&lt;/code&gt;.&lt;/strong&gt; chrony has native PPS support and a clean socket backend, so you skip the from-source NTP compile entirely.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Current Raspberry Pi OS paths.&lt;/strong&gt; On Bookworm (and Trixie) the boot config lives at &lt;strong&gt;&lt;code&gt;/boot/firmware/config.txt&lt;/code&gt;&lt;/strong&gt;, not the old &lt;code&gt;/boot/config.txt&lt;/code&gt; (which is now just a placeholder).&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;How it all fits together&lt;/h2&gt;&lt;p&gt;Before wiring anything up, here&amp;#39;s a quick overview :&lt;/p&gt;&lt;pre&gt;&lt;code&gt;GPS/RTC HAT (u-blox + PPS)           Raspberry Pi 3 / 4 (host)
 ┌───────────────────────────┐    ┌──────────────────────────────────────────────┐
 │  receiver                 │    │                                              │
 │   • NMEA over UART  ──────┼──▶│  /dev/serial0 ─▶ gpsd ─┐                      │
 │   • PPS on GPIO18   ──────┼──▶│  /dev/pps0 ────────────┼─▶ chrony (stratum 1) │
 └───────────────────────────┘   │                        │        │  serves NTP │
                                 │   gpsd JSON :2947 ─┐    │        ▼   to LAN    │
                                 │   chronyc -c ──────┼────┴─▶ Rust daemon        │
                                 │   (optional) NAVCEN ───▶  :8080 (configurable) │
                                 │                    ├─▶ /data     (SSE telemetry)│
                                 │                    ├─▶ /satinfo  (opt. sat info)│
                                 │                    └─▶ /         (dashboard)   │
                                 └───────────────────────────────┬───────────────┘
                                                                │
                                                   browser ◀────┘  dashboard&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The timekeeping path&lt;/strong&gt; — gpsd reads NMEA + PPS and feeds chrony; chrony disciplines the kernel clock and serves NTP to my network. &lt;em&gt;This&lt;/em&gt; is what makes it a stratum-1 server. If you stop reading after Part 6, you&amp;#39;ve got a fully working time server.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The telemetry path&lt;/strong&gt; — a small daemon written in Rust that reads the &lt;em&gt;same&lt;/em&gt; gpsd data plus chrony&amp;#39;s stats and streams them to the dashboard over Server-Sent Events. It&amp;#39;s strictly read-only and has &lt;strong&gt;zero effect on timekeeping accuracy&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;What you&amp;#39;ll need&lt;/h2&gt;&lt;p&gt;Here&amp;#39;s the parts list I used:&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Part&lt;/th&gt;&lt;th&gt;Notes&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Raspberry Pi 3 or 4&lt;/td&gt;&lt;td&gt;Both work identically here. The Pi 4 has dedicated Gigabit Ethernet; on the Pi 3, Ethernet shares the USB bus, so keep other USB devices off it. The &lt;strong&gt;Pi 5&lt;/strong&gt; needs different UART steps and isn&amp;#39;t covered.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPS HAT &lt;strong&gt;with PPS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;I used the &lt;a href=&quot;https://store.uputronics.com/products/raspberry-pi-gps-rtc-expansion-board&quot;&gt;Uputronics Raspberry Pi GPS/RTC Expansion Board&lt;/a&gt;, and it&amp;#39;s what this guide is written against. PPS is mandatory for stratum-1; NMEA alone is only good to a few hundred milliseconds.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPS antenna (active, timing-grade)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.digikey.com/en/products/detail/pctel-inc/3978D-HR-DH-W/13687637&quot;&gt;&lt;strong&gt;Amphenol PCTEL 3978D-HR-DH-W&lt;/strong&gt;&lt;/a&gt; — the exact antenna I used: a weatherproof (IP67) GPS &lt;strong&gt;L1 dome antenna&lt;/strong&gt; with a built-in LNA + filter (~40 dB gain) and a TNC-female connector. A real step up from a puck. Needs a clear-ish view of the sky.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Antenna mounting bracket&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.digikey.com/en/products/detail/amphenol-pctel/MMK1925/13687543&quot;&gt;&lt;strong&gt;Amphenol PCTEL MMK1925&lt;/strong&gt;&lt;/a&gt; — the stainless-steel L-bracket for the WS397x-series dome (fits the 3978D). This and the antenna above are what I actually mounted.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Antenna coax&lt;/td&gt;&lt;td&gt;A run with the right ends for your antenna and HAT (see the note below). I didn&amp;#39;t spring for timing-grade coax — I used a cheap &lt;a href=&quot;https://www.amazon.com/TUOLNK-Extension-Adapter-Wireless-Devices/dp/B09L3V38HD/&quot;&gt;SMA extension cable like this one&lt;/a&gt; and it&amp;#39;s been perfectly fine.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;All in all, the project cost ~$240 (inc. shipping, tax, etc). I didn&amp;#39;t include the cost of a raspberry pi since I had one unused from a prior project, but assuming you bought a new Pi; you are ~$360.&lt;/p&gt;&lt;h2&gt;Notes before we get started&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Check your HAT&amp;#39;s PPS pin.&lt;/strong&gt; This guide assumes &lt;strong&gt;GPIO18&lt;/strong&gt; (the Uputronics default). Some HATs (e.g. Adafruit) use &lt;strong&gt;GPIO4&lt;/strong&gt;. Adjust the &lt;code&gt;gpiopin=&lt;/code&gt; value accordingly. Guess wrong and PPS will simply never show up.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Antenna connector &amp;amp; bias (if you&amp;#39;re using the dome antenna above).&lt;/strong&gt; The 3978D outputs &lt;strong&gt;TNC female&lt;/strong&gt;, while most GPS HATs (Uputronics included) use &lt;strong&gt;SMA&lt;/strong&gt; — so plan a coax run with the right ends (TNC-male at the antenna, SMA-male at the HAT) or grab an adapter. It&amp;#39;s an &lt;strong&gt;active&lt;/strong&gt; antenna (built-in LNA), so the HAT has to supply DC bias voltage on the coax; the Uputronics HATs do this, but confirm yours does. Being IP67 and bracket-mounted, it&amp;#39;s meant to live outdoors on a mast with a clear sky view.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;You don&amp;#39;t have to mount it outdoors.&lt;/strong&gt; The 3978D is a weatherproof, IP67, mast-mount dome. It&amp;#39;s &lt;em&gt;built&lt;/em&gt; to bolt onto a roof and shrug off the weather. I didn&amp;#39;t put it on a roof. I bolted it to its MMK1925 bracket, set the whole thing up in my attic under asphalt shingles and 5/8&amp;quot; OSB, and ran it back to the HAT with a cheap SMA extension cable instead of proper timing-grade coax. On paper that&amp;#39;s leaving signal on the table three different ways. In practice it&amp;#39;s been tracking ~16-20 satellites and holding a sub-microsecond lock the entire time. So: buy the better antenna over fancy cable if you are on a limited budget and don&amp;#39;t let &amp;quot;needs a clear view of the sky&amp;quot; scare you into a rooftop install (especially if you are HOA bound and limited to what you can mount outside). An attic on the sky-facing side of the house is likely going to do it for you.&lt;/p&gt;&lt;h2&gt;Part 1 — The base OS&lt;/h2&gt;&lt;p&gt;Flash &lt;strong&gt;Raspberry Pi OS Lite (64-bit)&lt;/strong&gt; with Raspberry Pi Imager. In the Imager&amp;#39;s advanced settings (the gear icon), enable SSH and set the hostname (I&amp;#39;ll use &lt;code&gt;timeserver&lt;/code&gt; for this guide) and locale &lt;em&gt;before&lt;/em&gt; writing. Note: this Pi runs headless, which means you don&amp;#39;t have a monitor connected to it, so you want to be able to reach it on first boot.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A word on Bookworm vs Trixie.&lt;/strong&gt; As of mid-2026 there are active reports of a &lt;strong&gt;Trixie serial regression&lt;/strong&gt; where the GPIO UART stops receiving GPS data on hardware that worked fine on Bookworm (a suspected kernel/PL011 driver issue). For a device whose &lt;em&gt;entire job&lt;/em&gt; is reliable time, Bookworm might be the safer choice today; but so far things have worked fine for me. The config paths and overlays are identical — but if NMEA never appears despite correct wiring, jump to the Trixie diagnostic in Troubleshooting. There&amp;#39;s also a Debian 12 vs 13 appendix at the bottom.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Boot, SSH to the Pi, and update first:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt full-upgrade -y
sudo reboot&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Part 2 — Freeing up the hardware UART&lt;/h2&gt;&lt;p&gt;Here&amp;#39;s the first &amp;quot;gotcha&amp;quot; the Pi throws at you. The Pi 3/4 wire the &lt;em&gt;good&lt;/em&gt; UART (PL011) to the onboard Bluetooth by default. We need that UART for the GPS, and we also need to stop Linux from using the serial port as a login console.&lt;/p&gt;&lt;h3&gt;2a. Disable the serial login shell (but keep the hardware port)&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;sudo raspi-config&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Under &lt;strong&gt;Interface Options → Serial Port&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;em&gt;login shell accessible over serial?&lt;/em&gt; → &lt;strong&gt;No&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;em&gt;serial port hardware enabled?&lt;/em&gt; → &lt;strong&gt;Yes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Choose Finish but &lt;strong&gt;don&amp;#39;t reboot yet&lt;/strong&gt;, we&amp;#39;ve got more config to add, and I&amp;#39;d rather reboot once.&lt;/p&gt;&lt;h3&gt;2b. Disable Bluetooth to reclaim the UART&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;sudo vi /boot/firmware/config.txt&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New to &lt;code&gt;vi&lt;/code&gt;?&lt;/strong&gt; Here&amp;#39;s the reader&amp;#39;s digest: press &lt;code&gt;i&lt;/code&gt; to start typing (insert mode), make your edits, then hit &lt;code&gt;Esc&lt;/code&gt; and type &lt;code&gt;:wq&lt;/code&gt; followed by Enter to &lt;strong&gt;w&lt;/strong&gt;rite and &lt;strong&gt;q&lt;/strong&gt;uit. If you fat-finger something and want to bail without saving, &lt;code&gt;Esc&lt;/code&gt; then &lt;code&gt;:q!&lt;/code&gt; throws your changes away. That&amp;#39;s genuinely 90% of what you need to survive &lt;code&gt;vi&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Add this at the end (we&amp;#39;ll drop the PPS line in here too in Part 3, so it&amp;#39;s a single reboot):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# Reclaim the PL011 UART for GPS by disabling onboard Bluetooth
enable_uart=1
dtoverlay=disable-bt&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;Older guides use &lt;code&gt;dtoverlay=pi3-disable-bt&lt;/code&gt;; the current canonical name is just &lt;code&gt;disable-bt&lt;/code&gt;. &lt;code&gt;raspi-config&lt;/code&gt; may have already added an &lt;code&gt;enable_uart=1&lt;/code&gt; line — a duplicate is harmless, but you can keep just one if it bugs you.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Then stop the Bluetooth-UART service:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl disable hciuart&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;On a &lt;strong&gt;Lite image (and commonly on Trixie)&lt;/strong&gt; this may report &lt;code&gt;Unit hciuart.service does not exist&lt;/code&gt; — and that&amp;#39;s totally fine. It ships with the &lt;code&gt;pi-bluetooth&lt;/code&gt; package, which isn&amp;#39;t always installed, and &lt;code&gt;disable-bt&lt;/code&gt; already turns Bluetooth off at the device-tree level. The overlay is what actually matters here; this step is just belt-and-suspenders.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2&gt;Part 3 — Enabling PPS&lt;/h2&gt;&lt;p&gt;PPS (pulse-per-second) is the secret sauce. NMEA sentences tell you &lt;em&gt;what&lt;/em&gt; second it is; the PPS pulse tells you &lt;em&gt;exactly&lt;/em&gt; when that second begins, down to the nanosecond. No PPS, no real stratum-1.&lt;/p&gt;&lt;h3&gt;3a. Load the PPS-over-GPIO overlay&lt;/h3&gt;&lt;p&gt;Still in &lt;code&gt;/boot/firmware/config.txt&lt;/code&gt;, add (adjust &lt;code&gt;gpiopin&lt;/code&gt; for your HAT):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# Pulse-Per-Second input on GPIO18
dtoverlay=pps-gpio,gpiopin=18&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then load the kernel module at boot and reboot so both the UART and PPS changes take effect:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;echo &amp;#39;pps-gpio&amp;#39; | sudo tee -a /etc/modules
sudo reboot&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;3b. Verify raw GPS and PPS&lt;/h3&gt;&lt;p&gt;First confirm the UART is on the GPIO header, then read raw NMEA:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls -l /dev/serial0        # expect: /dev/serial0 -&amp;gt; ttyAMA0
sudo cat /dev/serial0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Always use &lt;strong&gt;&lt;code&gt;/dev/serial0&lt;/code&gt;&lt;/strong&gt; — it&amp;#39;s a symlink that always points to whichever UART is on the GPIO header, so you don&amp;#39;t have to care whether it&amp;#39;s &lt;code&gt;ttyAMA0&lt;/code&gt; or &lt;code&gt;ttyS0&lt;/code&gt; today. &lt;code&gt;Ctrl-C&lt;/code&gt; to stop.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;If you see garbled characters instead of clean &lt;code&gt;$GNRMC&lt;/code&gt;/&lt;code&gt;$GNGGA&lt;/code&gt; lines, don&amp;#39;t panic, that&amp;#39;s a baud-rate mismatch, not a fault.&lt;/strong&gt; Bytes are flowing; the port&amp;#39;s just reading them at the wrong speed. Set the rate explicitly and re-read until it&amp;#39;s clean:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo stty -F /dev/serial0 9600 raw   &amp;amp;&amp;amp; sudo cat /dev/serial0   # common u-blox default
sudo stty -F /dev/serial0 38400 raw  &amp;amp;&amp;amp; sudo cat /dev/serial0
sudo stty -F /dev/serial0 115200 raw &amp;amp;&amp;amp; sudo cat /dev/serial0   # mine with the Uputronics unit&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Write down the rate that produces readable NMEA, you&amp;#39;ll need it for gpsd in Part 4.&lt;/strong&gt; It&amp;#39;s a property of your GPS &lt;em&gt;module&lt;/em&gt;, not the OS. Many u-blox modules use 9600, but others (including some Uputronics units) run at &lt;strong&gt;115200&lt;/strong&gt;. Mine was 115200.&lt;/p&gt;&lt;p&gt;Now confirm the pulse itself. This needs a satellite fix; most HATs blink a timepulse LED once they&amp;#39;ve locked:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo apt install -y pps-tools
sudo ppstest /dev/pps0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You want a new &lt;code&gt;assert&lt;/code&gt; line every second, timestamped right on the whole second:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;source 0 - assert 1699999590.000001416, sequence: 197334 - clear ...
source 0 - assert 1699999591.000000698, sequence: 197335 - clear ...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;No output usually just means no fix yet, wait a couple mins or try moving the antenna to a different location. If you are running the antenna in a faraday cage, expect no results since it won&amp;#39;t find a satellite.&lt;/p&gt;&lt;h2&gt;Part 4 — gpsd&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;sudo apt install -y gpsd gpsd-clients
sudo vi /etc/default/gpsd&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Point it at your HAT (using the baud rate you found in Part 3b):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;START_DAEMON=&amp;quot;true&amp;quot;
USBAUTO=&amp;quot;false&amp;quot;
DEVICES=&amp;quot;/dev/serial0 /dev/pps0&amp;quot;
GPSD_OPTIONS=&amp;quot;-n -s 115200&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;-n&lt;/code&gt; polls the GPS immediately at boot; &lt;code&gt;-s 115200&lt;/code&gt; pins the serial speed so gpsd doesn&amp;#39;t autobaud its way into garbage. Enable and check:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl enable --now gpsd
sudo systemctl restart gpsd      # ensure it picks up the new config
gpsmon        # or: cgps -s&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;gpsmon&lt;/code&gt; shows the raw feed (fast-scrolling UBX packets are normal and healthy); &lt;code&gt;cgps -s&lt;/code&gt; gives a calmer table. You want a &lt;strong&gt;3D fix&lt;/strong&gt;, satellites with good SNR, low DOP values, and a &lt;strong&gt;PPS&lt;/strong&gt; line with a near-zero offset. That PPS line is the confirmation I was chasing.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; gpsd takes exclusive control of the port. If you want to &lt;code&gt;cat /dev/serial0&lt;/code&gt; again for debugging, stop gpsd first: &lt;code&gt;sudo systemctl stop gpsd gpsd.socket&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2&gt;Part 5 — chrony with the socket backend&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;sudo apt install -y chrony&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here&amp;#39;s the key design point, and the reason chrony is such an upgrade over the old ntpd dance: &lt;strong&gt;gpsd hands the precise PPS timestamp to chrony through a Unix socket&lt;/strong&gt; (chrony&amp;#39;s &lt;code&gt;SOCK&lt;/code&gt; refclock). gpsd automatically writes to &lt;code&gt;/run/chrony.&amp;lt;device&amp;gt;.sock&lt;/code&gt; once chrony has created it — neatly sidestepping the classic headache where chrony drops privileges and can no longer read &lt;code&gt;/dev/pps0&lt;/code&gt; directly.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo vi /etc/chrony/chrony.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add this at the end:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# --- GPS + PPS reference clocks -------------------------------------------

# Coarse absolute time from gpsd (NMEA) via shared memory.
# &amp;#39;noselect&amp;#39; = never sets the clock, only gives the PPS pulse a whole-second
# label. Tune &amp;#39;offset&amp;#39; after calibration (Part 7d) if PPS won&amp;#39;t lock.
refclock SHM 0 refid GPS precision 1e-1 offset 0.0 delay 0.2 noselect

# Precise PPS via gpsd&amp;#39;s socket. gpsd writes here automatically.
# &amp;#39;lock GPS&amp;#39; anchors each pulse to the GPS second above.
refclock SOCK /run/chrony.pps0.sock refid PPS lock GPS prefer

# Serve time to your LAN (adjust to your subnet) and keep serving during
# brief GPS dropouts.
allow 192.168.0.0/24
local stratum 1

# Optional internet fallback if the antenna fails. Remove for air-gapped use.
pool 2.debian.pool.ntp.org iburst&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Restart both, in order — chrony first, so its socket exists by the time gpsd starts:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl restart chrony
sudo systemctl restart gpsd&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Confirm the socket exists (it should be owned by root and actually be a socket — note the leading &lt;code&gt;s&lt;/code&gt; in the permissions):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls -l /run/chrony.*.sock      # expect /run/chrony.pps0.sock&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Part 6 — Confirming you&amp;#39;ve actually got a stratum-1 server&lt;/h2&gt;&lt;p&gt;Give it 5 minutes to settle, then watch the sources roll in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;watch -n 2 chronyc sources -v&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You&amp;#39;re looking for &lt;code&gt;#*&lt;/code&gt; next to &lt;strong&gt;PPS&lt;/strong&gt;. The asterisk means it&amp;#39;s the selected source disciplining the clock. It starts at &lt;code&gt;#?&lt;/code&gt; (not enough samples yet), climbs its reachability register (&lt;code&gt;0 → 1 → 3 → 7 → 17 → 37 → 77 → 377&lt;/code&gt;), then finally promotes to &lt;code&gt;#*&lt;/code&gt;. The internet servers drop to &lt;code&gt;^-&lt;/code&gt; (background sanity checks) once PPS takes over. Watching that register tick up is weirdly satisfying:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;MS Name/IP address   Stratum Poll Reach LastRx Last sample
=========================================================================
#? GPS                     0    4  377     14   +42ms[  +42ms] +/- 200ms
#* PPS                     0    4  377     13   -242ns[ -324ns] +/- 1095ns
^- 2.debian.pool.ntp.org   2    6   77     45   -437us[ -436us] +/-  13ms&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then confirm the server itself:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;chronyc tracking&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Look for &lt;strong&gt;&lt;code&gt;Stratum : 1&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;Reference ID … (PPS)&lt;/code&gt;&lt;/strong&gt;, and a &lt;code&gt;System time&lt;/code&gt; offset down in the sub-microsecond range. That, right there, is a working stratum-1 time server. I may have taken a screenshot.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reading the numbers:&lt;/strong&gt; &lt;code&gt;System time&lt;/code&gt; / &lt;code&gt;Last offset&lt;/code&gt; are your &lt;em&gt;current&lt;/em&gt; accuracy (nanoseconds-to-microseconds once locked). &lt;code&gt;RMS offset&lt;/code&gt; looks alarming at first (hundreds of µs) because it&amp;#39;s a rolling average still dominated by the noisy warm-up; it falls steadily the longer it runs, so don&amp;#39;t judge it too early. &lt;code&gt;Root delay&lt;/code&gt; near zero and &lt;code&gt;Reference ID&lt;/code&gt; = PPS confirm a direct hardware lock.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The falseticker trap.&lt;/strong&gt; chrony will reject PPS if the GPS (NMEA) label is more than ±200 ms off the true second. If PPS stays stuck at &lt;code&gt;#?&lt;/code&gt;, that&amp;#39;s almost always the culprit, calibrate the offset (Part 7d).&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;At this point the time server itself is done. &lt;strong&gt;Below is the fun part of visualizing the setup.&lt;/strong&gt; If you just wanted accurate time, congratulations, you can stop here.&lt;/p&gt;&lt;h2&gt;Part 7 — The telemetry daemon&lt;/h2&gt;&lt;p&gt;Now to create a live dashboard to visualize everything. The daemon does four things:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Connects to gpsd&amp;#39;s JSON socket on &lt;code&gt;127.0.0.1:2947&lt;/code&gt; — the same protocol &lt;code&gt;libgps&lt;/code&gt; speaks, so I get identical data without any C FFI.&lt;/li&gt;



&lt;li&gt;Polls chrony once a second with &lt;code&gt;chronyc -c tracking&lt;/code&gt; (the &lt;code&gt;-c&lt;/code&gt; flag hands back machine-readable CSV from chrony&amp;#39;s command socket).&lt;/li&gt;



&lt;li&gt;Merges both, streams them to the browser over SSE at &lt;code&gt;/data&lt;/code&gt;, and serves the dashboard.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;(Optional, off by default)&lt;/strong&gt; fetches and caches the NAVCEN GPS almanac and serves it at &lt;code&gt;/satinfo&lt;/code&gt; for satellite-health enrichment (more in Part 8).&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Get the code, the daemon and dashboard live on GitHub: &lt;a href=&quot;https://github.com/JackStromberg/gps-timeserver-daemon&quot;&gt;JackStromberg/gps-timeserver-daemon&lt;/a&gt;. Clone it directly onto the Pi:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo apt install -y git
git clone https://github.com/JackStromberg/gps-timeserver-daemon.git
cd gps-timeserver-daemon
ls -al&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should end up with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gps-timeserver-daemon/
├── Cargo.toml
├── src/main.rs
└── static/index.html      # already set to live mode (USE_SIMULATION = false)&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;7a. Install Rust and build&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;curl --proto &amp;#39;=https&amp;#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh   # press Enter for defaults
source &amp;quot;$HOME/.cargo/env&amp;quot;
cargo --version                                                  # should print a version
sudo apt install -y build-essential                              # C linker (Lite images lack it)
cd gps-timeserver-daemon
cargo build --release&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;cargo: command not found&lt;/code&gt; right after installing?&lt;/strong&gt; The installer can&amp;#39;t modify an already-running shell&amp;#39;s &lt;code&gt;PATH&lt;/code&gt;. Run &lt;code&gt;source &amp;quot;$HOME/.cargo/env&amp;quot;&lt;/code&gt; (or just open a new terminal). If &lt;code&gt;ls ~/.cargo/bin/cargo&lt;/code&gt; doesn&amp;#39;t exist, the install didn&amp;#39;t finish — re-run the &lt;code&gt;curl … | sh&lt;/code&gt; line.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;error: linker &amp;#39;cc&amp;#39; not found&lt;/code&gt;?&lt;/strong&gt; Install &lt;code&gt;build-essential&lt;/code&gt; (above) and rebuild.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Fair warning: the first build on a Pi is &lt;strong&gt;slow&lt;/strong&gt;. It compiles tokio, axum, reqwest, and the whole rustls TLS stack from scratch (several minutes), and it may look completely frozen at the final link step. That&amp;#39;s normal. Subsequent builds are incremental and quick.&lt;/p&gt;&lt;h3&gt;7b. Run it&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;./target/release/gps-timeserver-daemon&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It prints its listen address and stays running (it&amp;#39;s serving, so it won&amp;#39;t hand you back a prompt). Open &lt;code&gt;http://&amp;lt;pi-ip&amp;gt;:8080&lt;/code&gt; from a browser on your LAN and you should see the dashboard light up.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;The port is configurable — see Part 8. If &lt;code&gt;8080&lt;/code&gt; is already taken (a Docker service, say), you&amp;#39;ll get &lt;code&gt;AddrInUse&lt;/code&gt;; set a different &lt;code&gt;PORT&lt;/code&gt; rather than editing code.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h3&gt;7c. The &lt;code&gt;/data&lt;/code&gt; contract&lt;/h3&gt;&lt;p&gt;The daemon emits one JSON object per second in this shape (the dashboard reads exactly these field names):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;{
  &amp;quot;timestamp&amp;quot;: &amp;quot;2026-07-07T12:34:56Z&amp;quot;,
  &amp;quot;time&amp;quot;:   { &amp;quot;gps_time&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;system_time&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;offset_us&amp;quot;: 0.42,
              &amp;quot;time_since_last_fix&amp;quot;: 0.3, &amp;quot;leap_seconds&amp;quot;: 18 },
  &amp;quot;gps&amp;quot;:    { &amp;quot;mode&amp;quot;: 3, &amp;quot;satellites_visible&amp;quot;: 12, &amp;quot;satellites_used&amp;quot;: 9,
              &amp;quot;hdop&amp;quot;: 0.8, &amp;quot;vdop&amp;quot;: 1.1, &amp;quot;pdop&amp;quot;: 1.3, &amp;quot;gdop&amp;quot;: 1.5, &amp;quot;tdop&amp;quot;: 0.7,
              &amp;quot;ept&amp;quot;: 0.005, &amp;quot;latitude&amp;quot;: 51.5, &amp;quot;longitude&amp;quot;: -0.12, &amp;quot;altitude&amp;quot;: 35.2,
              &amp;quot;epx&amp;quot;: 3.1, &amp;quot;epy&amp;quot;: 4.2, &amp;quot;epv&amp;quot;: 6.0, &amp;quot;track&amp;quot;: 0.0, &amp;quot;speed&amp;quot;: 0.0,
              &amp;quot;climb&amp;quot;: 0.0, &amp;quot;eps&amp;quot;: 0.5 },
  &amp;quot;chrony&amp;quot;: { &amp;quot;reference_id&amp;quot;: &amp;quot;PPS&amp;quot;, &amp;quot;stratum&amp;quot;: 1, &amp;quot;system_time&amp;quot;: 0.0000004,
              &amp;quot;last_offset&amp;quot;: 0.0000004, &amp;quot;rms_offset&amp;quot;: 0.0000012,
              &amp;quot;frequency_ppm&amp;quot;: -2.3, &amp;quot;residual_freq_ppm&amp;quot;: 0.001, &amp;quot;skew_ppm&amp;quot;: 0.02,
              &amp;quot;root_delay&amp;quot;: 0.00001, &amp;quot;root_dispersion&amp;quot;: 0.00002,
              &amp;quot;update_interval&amp;quot;: 16.0, &amp;quot;leap_status&amp;quot;: &amp;quot;Normal&amp;quot; },
  &amp;quot;device&amp;quot;: { &amp;quot;path&amp;quot;: &amp;quot;/dev/serial0&amp;quot;, &amp;quot;driver&amp;quot;: &amp;quot;u-blox&amp;quot;, &amp;quot;subtype&amp;quot;: &amp;quot;...&amp;quot;,
              &amp;quot;bps&amp;quot;: 115200, &amp;quot;parity&amp;quot;: &amp;quot;N&amp;quot;, &amp;quot;native&amp;quot;: true, &amp;quot;cycle&amp;quot;: 1.0, &amp;quot;mincycle&amp;quot;: 1.0 },
  &amp;quot;version&amp;quot;:{ &amp;quot;release&amp;quot;: &amp;quot;3.25&amp;quot;, &amp;quot;proto_major&amp;quot;: 3, &amp;quot;proto_minor&amp;quot;: 15 },
  &amp;quot;satellites&amp;quot;: [
    { &amp;quot;prn&amp;quot;: 5, &amp;quot;system&amp;quot;: &amp;quot;GPS&amp;quot;, &amp;quot;elevation&amp;quot;: 70, &amp;quot;azimuth&amp;quot;: 251, &amp;quot;snr&amp;quot;: 42, &amp;quot;used&amp;quot;: true }
  ]
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Telemetry::to_json()&lt;/code&gt; in &lt;code&gt;src/main.rs&lt;/code&gt; is the single source of truth for this contract — if you want to add a field, that&amp;#39;s the one place to touch.&lt;/p&gt;&lt;h3&gt;7d. Calibrating the GPS offset (optional)&lt;/h3&gt;&lt;p&gt;If PPS refuses to lock, let it run ~15 minutes, then read the measured GPS offset:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;chronyc sourcestats&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Take the GPS source&amp;#39;s &lt;strong&gt;Offset&lt;/strong&gt; (say &lt;code&gt;+512ms&lt;/code&gt;), convert to seconds, and set it as &lt;code&gt;offset&lt;/code&gt; on the &lt;code&gt;SHM 0&lt;/code&gt; line in &lt;code&gt;chrony.conf&lt;/code&gt; (e.g. &lt;code&gt;offset 0.512&lt;/code&gt;). Restart chrony. This nudges the NMEA label back inside the ±200 ms window so PPS gets accepted — the fix for that falseticker trap I mentioned above.&lt;/p&gt;&lt;h2&gt;Part 8 — Configuration via environment variables&lt;/h2&gt;&lt;p&gt;I wanted to be able to change behavior without recompiling, so the daemon reads a handful of environment variables at startup. Set them when running manually, or via &lt;code&gt;Environment=&lt;/code&gt; lines in the systemd unit (Part 9).&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Variable&lt;/th&gt;&lt;th&gt;Default&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;code&gt;PORT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;8080&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Port to bind (binds &lt;code&gt;0.0.0.0:PORT&lt;/code&gt;).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LISTEN_ADDR&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;em&gt;(unset)&lt;/em&gt;&lt;/td&gt;&lt;td&gt;Full &lt;code&gt;host:port&lt;/code&gt;; overrides &lt;code&gt;PORT&lt;/code&gt;. Use &lt;code&gt;127.0.0.1:8088&lt;/code&gt; to serve only locally, &lt;code&gt;0.0.0.0:8088&lt;/code&gt; for the LAN.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SATINFO_ENABLED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;em&gt;(off)&lt;/em&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;1&lt;/code&gt;/&lt;code&gt;true&lt;/code&gt;/&lt;code&gt;yes&lt;/code&gt;/&lt;code&gt;on&lt;/code&gt; enables the optional NAVCEN satellite-info fetcher. &lt;strong&gt;Off means the daemon makes zero outbound network calls&lt;/strong&gt; — safe for air-gapped setups.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SATINFO_INTERVAL_HOURS&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;168&lt;/code&gt; (weekly)&lt;/td&gt;&lt;td&gt;How often to refresh the NAVCEN data. The constellation changes only a few times a year, so weekly (or &lt;code&gt;720&lt;/code&gt; ≈ monthly) is plenty.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SATINFO_URL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;NAVCEN YUMA almanac&lt;/td&gt;&lt;td&gt;Override the source if needed.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h3&gt;The optional satellite-info fetcher&lt;/h3&gt;&lt;p&gt;When &lt;code&gt;SATINFO_ENABLED=1&lt;/code&gt;, a background task fetches the &lt;strong&gt;NAVCEN GPS almanac&lt;/strong&gt; (US Coast Guard, public-domain US-government data), caches it in memory, and serves it at &lt;code&gt;/satinfo&lt;/code&gt;. The dashboard uses it to add live &lt;strong&gt;health&lt;/strong&gt; status to each GPS satellite&amp;#39;s hover tooltip. On failure it retries in an hour; on success it waits the full interval. Left disabled (the default), &lt;code&gt;/satinfo&lt;/code&gt; returns &lt;code&gt;{&amp;quot;enabled&amp;quot;: false}&lt;/code&gt; and the dashboard silently falls back to its built-in reference table — so nothing breaks either way.&lt;/p&gt;&lt;p&gt;Quick checks once you&amp;#39;ve enabled it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;journalctl -u timeserver-dashboard -n 20 --no-pager   # look for: satinfo: fetched N satellites
curl -s localhost:8080/satinfo | head -c 300          # expect &amp;quot;enabled&amp;quot;:true and a satellites object&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;On data sources &amp;amp; licensing&lt;/strong&gt; (not legal advice): NAVCEN is public-domain US-government data — no account, redistribution-safe. The dashboard&amp;#39;s built-in reference table is assembled from public GPS records. If you instead point live mode at CelesTrak, respect their access etiquette (cache; don&amp;#39;t poll more than roughly every 2 hours) and cite them. There&amp;#39;s a fuller Licensing appendix at the bottom.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2&gt;Part 9 — Running it at boot&lt;/h2&gt;&lt;p&gt;I want this thing to just come back on its own after a power blip, so let&amp;#39;s give it a systemd unit:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo vi /etc/systemd/system/timeserver-dashboard.service&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;[Unit]
Description=GPS Timeserver Dashboard
After=network-online.target gpsd.service chrony.service
Wants=network-online.target

[Service]
# Adjust User and paths to where you put the project.
User=pi
WorkingDirectory=/home/pi/gps-timeserver-daemon
ExecStart=/home/pi/gps-timeserver-daemon/target/release/gps-timeserver-daemon
Restart=on-failure
RestartSec=3

# Optional configuration (see Part 8):
Environment=PORT=8088
# Environment=SATINFO_ENABLED=1
# Environment=SATINFO_INTERVAL_HOURS=168

[Install]
WantedBy=multi-user.target&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;WorkingDirectory&lt;/code&gt; matters more than it looks.&lt;/strong&gt; The daemon serves &lt;code&gt;static/index.html&lt;/code&gt; relative to where it runs, and systemd does &lt;em&gt;not&lt;/em&gt; inherit your shell&amp;#39;s current directory. Point this at the wrong place and you&amp;#39;ll get a &lt;strong&gt;404&lt;/strong&gt; for the dashboard.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Enable and verify:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl enable --now timeserver-dashboard
systemctl status timeserver-dashboard          # expect: active (running)
journalctl -u timeserver-dashboard -n 5 --no-pager   # confirm the listen address&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Whenever you edit the unit file&lt;/strong&gt; (say, to change an &lt;code&gt;Environment=&lt;/code&gt; line), run &lt;code&gt;sudo systemctl daemon-reload&lt;/code&gt; &lt;strong&gt;and then&lt;/strong&gt; &lt;code&gt;sudo systemctl restart timeserver-dashboard&lt;/code&gt;. Skipping the reload is the classic &amp;quot;my change didn&amp;#39;t take&amp;quot; gotcha. &lt;code&gt;systemctl show timeserver-dashboard -p Environment&lt;/code&gt; prints what systemd is &lt;em&gt;actually&lt;/em&gt; passing, which is handy when you&amp;#39;re sure you fixed it but it disagrees.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;One nice quality-of-life note: editing only &lt;code&gt;static/index.html&lt;/code&gt; (HTML/CSS/JS) needs &lt;strong&gt;no rebuild and no restart&lt;/strong&gt; — the daemon serves it from disk at request time. Just hard-refresh the browser (&lt;strong&gt;Ctrl-Shift-R&lt;/strong&gt;). Only changes to &lt;code&gt;src/main.rs&lt;/code&gt; or &lt;code&gt;Cargo.toml&lt;/code&gt; require &lt;code&gt;cargo build --release&lt;/code&gt;.&lt;/p&gt;&lt;h2&gt;Part 10 — Serving time to the rest of the network&lt;/h2&gt;&lt;p&gt;Everything so far only disciplines the Pi&amp;#39;s &lt;em&gt;own&lt;/em&gt; clock. To let other machines sync from it, chrony has to answer NTP requests — and it refuses by default, which is a good safety default but not what we want here.&lt;/p&gt;&lt;h3&gt;10a. Match the allow line to your LAN&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;hostname -I               # your Pi&amp;#39;s IP, e.g. 192.168.1.50&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the Pi is &lt;code&gt;192.168.1.50&lt;/code&gt;, your subnet is likely &lt;code&gt;192.168.1.0/24&lt;/code&gt;. Edit &lt;code&gt;chrony.conf&lt;/code&gt; so the &lt;code&gt;allow&lt;/code&gt; line matches — a whole subnet (&lt;code&gt;allow 192.168.1.0/24&lt;/code&gt;), a single host (&lt;code&gt;allow 192.168.1.100&lt;/code&gt;), or &lt;code&gt;allow all&lt;/code&gt; only if you &lt;em&gt;deliberately&lt;/em&gt; mean to serve the public — then restart:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl restart chrony&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;10b. Confirm it&amp;#39;s serving&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;sudo ss -ulnp &amp;#39;sport = :123&amp;#39;    # something should be bound to UDP 123
chronyc clients                 # machines that have requested time (empty until clients connect)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you run a firewall on the same Raspberry Pi (&lt;code&gt;ufw&lt;/code&gt;, &lt;code&gt;nftables&lt;/code&gt;, or Docker-managed iptables), open NTP: &lt;code&gt;sudo ufw allow 123/udp&lt;/code&gt;. A plain Lite install has no firewall and needs nothing.&lt;/p&gt;&lt;h3&gt;10c. Point your clients at the Pi&lt;/h3&gt;&lt;p&gt;Your Pi is &lt;strong&gt;stratum 1&lt;/strong&gt;, so anything syncing to it becomes &lt;strong&gt;stratum 2&lt;/strong&gt; — perfect for a LAN. Here&amp;#39;s how I pointed a few common clients at it:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Router:&lt;/strong&gt; set its NTP server to the Pi&amp;#39;s IP — this pushes time locally to every device automatically, using it as an ntp source.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Linux:&lt;/strong&gt; add &lt;code&gt;server &amp;lt;pi-ip&amp;gt; iburst&lt;/code&gt; to &lt;code&gt;/etc/chrony/chrony.conf&lt;/code&gt;, restart chrony.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Windows:&lt;/strong&gt; &lt;code&gt;w32tm /config /manualpeerlist:&amp;quot;&amp;lt;pi-ip&amp;gt;&amp;quot; /syncfromflags:manual /update&lt;/code&gt; then &lt;code&gt;w32tm /resync&lt;/code&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;macOS:&lt;/strong&gt; System Settings → General → Date &amp;amp; Time, or &lt;code&gt;sudo sntp -sS &amp;lt;pi-ip&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Verify from a client with &lt;code&gt;chronyc -h &amp;lt;pi-ip&amp;gt; tracking&lt;/code&gt;, &lt;code&gt;sntp &amp;lt;pi-ip&amp;gt;&lt;/code&gt;, or &lt;code&gt;ntpdate -q &amp;lt;pi-ip&amp;gt;&lt;/code&gt;. Back on the Pi, &lt;code&gt;chronyc clients&lt;/code&gt; will list everyone pulling time from you.&lt;/p&gt;&lt;h2&gt;Part 11 — Actually using the dashboard&lt;/h2&gt;&lt;p&gt;Open &lt;code&gt;http://&amp;lt;pi-ip&amp;gt;:&amp;lt;port&amp;gt;&lt;/code&gt; (default &lt;code&gt;8080&lt;/code&gt;, or &lt;code&gt;8088&lt;/code&gt; in my examples above). Everything updates once per second from the live feed.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Time header.&lt;/strong&gt; A large clock with millisecond precision, plus GPS time, system time, and the chrony offset. The &lt;strong&gt;UTC / Local&lt;/strong&gt; toggle under the clock switches every time on the page between UTC and your browser&amp;#39;s local zone, and it remembers your choice across reloads.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Orbital globe (the hero panel, and my favorite).&lt;/strong&gt; A holographic Earth with each GNSS satellite placed in true 3D from its azimuth/elevation, color-coded by constellation, with beams running from the satellites in use down to a marker at your location.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Drag&lt;/strong&gt; to rotate (mouse or touch): horizontal spins around the poles, vertical tilts.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Home button&lt;/strong&gt; (top-right) or &lt;strong&gt;double-click&lt;/strong&gt; the globe to glide back to the default view.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hover a satellite&lt;/strong&gt; for its details: PRN, constellation, elevation, azimuth, SNR, and whether it&amp;#39;s in the solution — plus, for GPS, catalog facts (block, manufacturer, clock type, launch year, name, SVN) and, if &lt;code&gt;/satinfo&lt;/code&gt; is enabled, live health.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hover a legend entry&lt;/strong&gt; (GPS/GLONASS/Galileo/BeiDou/SBAS) for a one-line explanation of that constellation.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Status panels.&lt;/strong&gt; GPS Status, Chrony Status, Position &amp;amp; Navigation, and System Info. &lt;strong&gt;Hover any metric label&lt;/strong&gt; (they&amp;#39;ve got a dotted underline) for an explanation of what it means and what a good value looks like — HDOP, TDOP, EPX/EPY/EPV, the chrony offsets, and so on. I added these mostly so I&amp;#39;d stop having to look them up myself.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sky view + satellite table.&lt;/strong&gt; Polar az/el plot, plus a detailed per-satellite table.&lt;/p&gt;&lt;h3&gt;Satellite-info modes (dashboard side)&lt;/h3&gt;&lt;p&gt;Near the top of the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; in &lt;code&gt;static/index.html&lt;/code&gt;:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SATINFO_MODE&lt;/code&gt; — &lt;code&gt;&amp;#39;daemon&amp;#39;&lt;/code&gt; (default; asks this server&amp;#39;s &lt;code&gt;/satinfo&lt;/code&gt;, no CORS, falls back to the built-in table if the server has fetching disabled), &lt;code&gt;&amp;#39;offline&amp;#39;&lt;/code&gt; (built-in table only, never fetches), &lt;code&gt;&amp;#39;celestrak&amp;#39;&lt;/code&gt; (fetch CelesTrak directly from the browser; may hit CORS), or &lt;code&gt;&amp;#39;off&amp;#39;&lt;/code&gt;.&lt;/li&gt;



&lt;li&gt;The built-in table always supplies block/manufacturer/clock/name/launch; &lt;code&gt;/satinfo&lt;/code&gt; adds live health on top.&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Previewing with simulated data&lt;/h3&gt;&lt;p&gt;&lt;code&gt;static/index.html&lt;/code&gt; ships with &lt;code&gt;const USE_SIMULATION = false;&lt;/code&gt; (live). To preview the UI without any hardware — say you&amp;#39;re building this on your laptop before the HAT arrives — open a copy with it set to &lt;code&gt;true&lt;/code&gt;. It generates fake data (a fixed location, invented satellites, a locked stratum-1 state) so every visual works offline.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Heads up: the globe and all hover tooltips are mouse-based, so the hover interactions won&amp;#39;t appear on touchscreens (dragging the globe still works via touch).&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2&gt;Part 12 — Optional: running the dashboard in Docker&lt;/h2&gt;&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; containerize the &lt;strong&gt;dashboard daemon&lt;/strong&gt; — but &lt;strong&gt;keep gpsd + chrony on the host.&lt;/strong&gt; The kernel clock is a single host-wide resource; putting chrony in a container means granting it &lt;code&gt;SYS_TIME&lt;/code&gt; and steering the host clock across the container boundary — extra layers wrapped around your most timing-sensitive component. The daemon, on the other hand, is a read-only consumer and containerizes cleanly with zero precision impact.&lt;/p&gt;&lt;p&gt;Here&amp;#39;s an example multi-stage &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# Build
FROM rust:1-bookworm AS build
WORKDIR /app
COPY Cargo.toml Cargo.lock* ./
COPY src ./src
RUN cargo build --release

# Runtime
FROM debian:bookworm-slim
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y --no-install-recommends \
      chrony ca-certificates &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /app/target/release/gps-timeserver-daemon /usr/local/bin/
COPY static ./static
CMD [&amp;quot;gps-timeserver-daemon&amp;quot;]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that &lt;code&gt;chrony&lt;/code&gt; is installed here only for its &lt;code&gt;chronyc&lt;/code&gt; client (the daemon shells out to it) — the container does &lt;strong&gt;not&lt;/strong&gt; run a chrony daemon. Run it sharing the host network and chrony&amp;#39;s command socket:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;docker build -t timeserver-dashboard .

docker run -d --name timeserver-dashboard \
  --network host \
  -e PORT=8088 \
  -e SATINFO_ENABLED=1 \
  -v /run/chrony:/run/chrony:ro \
  --restart unless-stopped \
  timeserver-dashboard&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--network host&lt;/code&gt; lets the daemon reach host gpsd at &lt;code&gt;127.0.0.1:2947&lt;/code&gt; and keeps &lt;code&gt;PORT&lt;/code&gt;/&lt;code&gt;LISTEN_ADDR&lt;/code&gt; working normally.&lt;/li&gt;



&lt;li&gt;Mounting &lt;code&gt;/run/chrony&lt;/code&gt; gives the container&amp;#39;s &lt;code&gt;chronyc&lt;/code&gt; access to chrony&amp;#39;s command socket.&lt;/li&gt;



&lt;li&gt;You do &lt;strong&gt;not&lt;/strong&gt; need &lt;code&gt;--device=/dev/serial0&lt;/code&gt; or &lt;code&gt;/dev/pps0&lt;/code&gt; here — the daemon never touches the hardware directly; it reads gpsd and chronyc. (Those devices only matter if you were containerizing gpsd/chrony too, which, again, I&amp;#39;d steer you away from.)&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;&lt;p&gt;Here&amp;#39;s a running list of things I&amp;#39;ve stumbled across:&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Symptom&lt;/th&gt;&lt;th&gt;Likely cause / fix&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cat /dev/serial0&lt;/code&gt; shows nothing&lt;/td&gt;&lt;td&gt;UART not freed. Confirm &lt;code&gt;dtoverlay=disable-bt&lt;/code&gt; is in &lt;strong&gt;&lt;code&gt;/boot/firmware/config.txt&lt;/code&gt;&lt;/strong&gt; (not &lt;code&gt;/boot/&lt;/code&gt;), &lt;code&gt;hciuart&lt;/code&gt; disabled, rebooted. Check &lt;code&gt;ls -l /dev/serial0&lt;/code&gt; points to &lt;code&gt;ttyAMA0&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cat /dev/serial0&lt;/code&gt; shows &lt;strong&gt;garbled text&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Baud-rate mismatch (not a fault). Set the rate with &lt;code&gt;stty -F /dev/serial0 &amp;lt;rate&amp;gt; raw&lt;/code&gt; and re-read; use the working rate in gpsd&amp;#39;s &lt;code&gt;-s&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Silent serial on &lt;strong&gt;Trixie&lt;/strong&gt; only, same HW worked on Bookworm&lt;/td&gt;&lt;td&gt;Suspected Trixie UART/PL011 regression. Diagnose: &lt;code&gt;pinctrl poll 14-15 &amp;amp;&lt;/code&gt;, then trigger GPS data — if &lt;strong&gt;GPIO15 (RX) never changes level&lt;/strong&gt;, no bytes are reaching the pin (a kernel issue, not your config). Try &lt;code&gt;linux-modules-extra-raspi&lt;/code&gt;, pin an older kernel, or fall back to Bookworm.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ppstest&lt;/code&gt; prints nothing&lt;/td&gt;&lt;td&gt;No fix yet, or wrong PPS pin. Give it sky view; verify &lt;code&gt;gpiopin=&lt;/code&gt; (4 vs 18).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;chrony PPS stuck at &lt;code&gt;#?&lt;/code&gt;&lt;/td&gt;&lt;td&gt;GPS/NMEA offset &amp;gt; 200 ms → falseticker. Calibrate the &lt;code&gt;SHM 0&lt;/code&gt; offset (Part 7d); make sure &lt;code&gt;/dev/pps0&lt;/code&gt; is in gpsd &lt;code&gt;DEVICES&lt;/code&gt; and &lt;code&gt;/run/chrony.pps0.sock&lt;/code&gt; exists.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dashboard &amp;quot;Waiting for data...&amp;quot;&lt;/td&gt;&lt;td&gt;Daemon can&amp;#39;t reach gpsd. Check &lt;code&gt;systemctl status timeserver-dashboard&lt;/code&gt; and that gpsd is up on &lt;code&gt;:2947&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dashboard returns &lt;strong&gt;404&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;WorkingDirectory&lt;/code&gt; in the unit doesn&amp;#39;t point at the project root, so &lt;code&gt;static/index.html&lt;/code&gt; isn&amp;#39;t found. Fix the path, &lt;code&gt;daemon-reload&lt;/code&gt;, restart.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Daemon exits with &lt;strong&gt;&lt;code&gt;AddrInUse&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The port&amp;#39;s taken (e.g. Docker on 8080). Set &lt;code&gt;Environment=PORT=8088&lt;/code&gt; (or another free port); &lt;code&gt;sudo ss -ltnp &amp;#39;sport = :8080&amp;#39;&lt;/code&gt; shows the culprit.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;/satinfo&lt;/code&gt; shows &lt;code&gt;enabled:false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SATINFO_ENABLED&lt;/code&gt; not set/true, or &lt;code&gt;daemon-reload&lt;/code&gt; skipped after editing the unit. &lt;code&gt;systemctl show … -p Environment&lt;/code&gt; to verify.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;/satinfo&lt;/code&gt; &lt;code&gt;enabled:true&lt;/code&gt; but &lt;code&gt;count:0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;NAVCEN fetch/parse failed (check the &lt;code&gt;error&lt;/code&gt; field and the journal). Network blip → it retries within an hour; persistent → check outbound HTTPS.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cargo: command not found&lt;/code&gt;&lt;/td&gt;&lt;td&gt;PATH not loaded: &lt;code&gt;source &amp;quot;$HOME/.cargo/env&amp;quot;&lt;/code&gt;. If &lt;code&gt;~/.cargo/bin/cargo&lt;/code&gt; is missing, re-run the rustup installer.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cargo build&lt;/code&gt; → &lt;code&gt;linker &amp;#39;cc&amp;#39; not found&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;sudo apt install -y build-essential&lt;/code&gt;, then rebuild.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Clients can&amp;#39;t sync&lt;/td&gt;&lt;td&gt;The &lt;code&gt;allow&lt;/code&gt; subnet in &lt;code&gt;chrony.conf&lt;/code&gt; has to match your LAN; open UDP/123 if you run a firewall.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Satellites look &lt;strong&gt;frozen&lt;/strong&gt; on the globe&lt;/td&gt;&lt;td&gt;Expected! GPS is MEO (~2 orbits/day) and moves only gradually in az/el; the receiver also updates angles slowly. Check back in 20–30 min and the pattern will have shifted.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2&gt;What you end up with&lt;/h2&gt;&lt;p&gt;So where does all this leave you? Two things:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;stratum-1 NTP server&lt;/strong&gt; disciplined by GPS + PPS, accurate to the microsecond or better, serving your whole LAN with &lt;strong&gt;no internet dependency&lt;/strong&gt;. Every device on my network now sets its clock from a little box in my attic pulling time straight out of the sky, and I find that quietly delightful.&lt;/li&gt;



&lt;li&gt;A &lt;strong&gt;live dashboard&lt;/strong&gt; showing the calculated time, full gpsd + chrony stats with hover explanations, an interactive 3D constellation globe with per-satellite detail, and a sky view — all fed by the same hardware over SSE, with a clean JSON contract you can extend however you like.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you want to keep tinkering, there are really just two files worth revisiting: &lt;code&gt;src/main.rs&lt;/code&gt; (where &lt;code&gt;Telemetry::to_json()&lt;/code&gt; defines the data contract) and &lt;code&gt;static/index.html&lt;/code&gt; (&lt;code&gt;METRIC_HELP&lt;/code&gt;, &lt;code&gt;GPS_SAT_DB&lt;/code&gt;, and the render functions). Everything I&amp;#39;d want to customize lives in one of those two places.&lt;/p&gt;&lt;p&gt;If you made it this far, congrats on your new clock! Your clock is now more accurate than it has any reason to be!&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;Appendix A — Debian 12 (Bookworm) vs Debian 13 (Trixie)&lt;/h2&gt;&lt;p&gt;Both work; most steps are identical. I &lt;strong&gt;verified everything on Debian 12 &amp;amp; 13&lt;/strong&gt; exactly as written above.&lt;/p&gt;&lt;figure&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Topic&lt;/th&gt;&lt;th&gt;Debian 12 / Bookworm&lt;/th&gt;&lt;th&gt;Debian 13 / Trixie&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Boot config path&lt;/td&gt;&lt;td&gt;&lt;code&gt;/boot/firmware/config.txt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Same&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;disable-bt&lt;/code&gt; / &lt;code&gt;pps-gpio&lt;/code&gt; overlays&lt;/td&gt;&lt;td&gt;Same&lt;/td&gt;&lt;td&gt;Same&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Serial device&lt;/td&gt;&lt;td&gt;&lt;code&gt;/dev/serial0 → ttyAMA0&lt;/code&gt; (always prefer &lt;code&gt;serial0&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;Same&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;systemctl disable hciuart&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Usually succeeds&lt;/td&gt;&lt;td&gt;Often &lt;code&gt;Unit … does not exist&lt;/code&gt; — harmless&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPIO UART receiving GPS&lt;/td&gt;&lt;td&gt;Reliable&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Regression risk&lt;/strong&gt; (mid-2026): no RX bytes despite correct config. Diagnose with &lt;code&gt;pinctrl poll 14-15&lt;/code&gt;; may need &lt;code&gt;linux-modules-extra-raspi&lt;/code&gt;, an older kernel, or Bookworm&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;gpsd / chrony&lt;/td&gt;&lt;td&gt;Stock; config as written&lt;/td&gt;&lt;td&gt;Newer; &lt;strong&gt;same config syntax&lt;/strong&gt;, &lt;code&gt;chronyc -c tracking&lt;/code&gt; CSV unchanged&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Recommendation&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Preferred&lt;/strong&gt; for a time server&lt;/td&gt;&lt;td&gt;Works, but verify the serial link early&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;Remember: serial &lt;strong&gt;baud rate&lt;/strong&gt; is a property of your GPS module, not the OS — it&amp;#39;s handled identically on both.&lt;/p&gt;&lt;h2&gt;Appendix B — Environment variables (quick reference)&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Daemon (systemd &lt;code&gt;Environment=&lt;/code&gt; or shell):&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Dashboard (&lt;code&gt;static/index.html&lt;/code&gt; constants):&lt;/strong&gt;&lt;/p&gt;&lt;h2&gt;Appendix C — Licensing &amp;amp; data sources&lt;/h2&gt;&lt;p&gt;&lt;em&gt;Not legal advice.&lt;/em&gt; For personal, non-commercial use you&amp;#39;re clear on all of the below.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPS orbital/almanac data&lt;/strong&gt; is US-government, public-domain. &lt;strong&gt;NAVCEN&lt;/strong&gt; (US Coast Guard) serves it with no account and is redistribution-safe — the recommended live source here.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;CelesTrak&lt;/strong&gt; (an alternative live source) redistributes the same government data and adds convenient PRN/block labeling. Respect their access etiquette: cache results and don&amp;#39;t poll more than roughly once every two hours; cite CelesTrak; note that it isn&amp;#39;t an official source. Commercial redistribution is a &amp;quot;contact them first&amp;quot; situation.&lt;/li&gt;



&lt;li&gt;The dashboard&amp;#39;s &lt;strong&gt;built-in reference table&lt;/strong&gt; is factual data (which PRN, block, launch year, manufacturer) assembled from public records; facts aren&amp;#39;t copyrightable.&lt;/li&gt;



&lt;li&gt;For anything &lt;strong&gt;commercial&lt;/strong&gt; or internet-facing at scale using, review each source&amp;#39;s current terms directly.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
</item>
<item>
<title>Linux Creator Linus Torvalds To Anti-AI Devs: Go Fork Yourself | HotHardware</title>
<link>https://hothardware.com/news/linus-torvalds-rejects-anti-ai-stance</link>
<enclosure type="image/jpeg" length="0" url="https://hothardware.com/contentimages/NewsItem/71137/content/16x9_2133x1200_highres-linus-torvalds-new-champions-tianjin-china-2012.jpg"></enclosure>
<guid isPermaLink="false">b-GEqsjQA3u2hf7T_shINxsoalJSrEpD8cm1Aw==</guid>
<pubDate>Fri, 17 Jul 2026 02:40:46 +0000</pubDate>
<description>Linus&#39;s stance is clear: Linux is about the technology, not ideology.</description>
<content:encoded>&lt;div&gt;&lt;a href=&quot;https://hothardware.com/photo-gallery/NewsItem/71137?image=big_hero-linus-torvalds-new-champions-tianjin-china-2012.jpg&amp;amp;tag=popup&quot;&gt;
&lt;picture&gt;&lt;img src=&quot;data:image/webp;base64,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&quot; alt=&quot;hero linus torvalds new champions tianjin china 2012&quot; title=&quot;&quot;/&gt;&lt;/picture&gt;
&lt;/a&gt;&lt;/div&gt;
The strength of open-source software is that it&amp;#39;s open, which is to say that anyone can contribute to it. Sometimes, this also means that your project can attract persons with conflicting worldviews. No open-source project is bigger than Linux itself, and recently the Linux Kernel project has been grappling with calls from certain contributors who feel that Linux should take an &lt;a href=&quot;https://hothardware.com/news/catly-dev-hisses-back-at-accusations-of-ai&quot;&gt;assertive anti-AI stance&lt;/a&gt;. Top-level maintainer and Linux creator Linux Torvalds has &amp;quot;put his foot down&amp;quot; on the issue, and his stance is clear: Linux is about the technology, not ideology.&lt;br/&gt;&lt;br/&gt;
Replying to a post where prominent Googler Roman Guschin remarks on the AI use recommendations of the Software Freedom Conservancy by calling them &amp;quot;anti-LLM in general&amp;quot;, Torvalds spoke up to agree, saying that &amp;quot;Linux is not one of those anti-AI projects, and if somebody has issues with that, they can do the open-source thing and fork it.&amp;quot; This is the same ethos Linus has always applied; he&amp;#39;s spent decades saying &amp;quot;show me the code&amp;quot; regardless of the &lt;a href=&quot;https://hothardware.com/news/linus-torvalds-rant-intel-stifled-ecc-memory&quot;&gt;controversy of the moment&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;div&gt;&lt;img src=&quot;data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&quot; alt=&quot;linus torvalds on ai in linux&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;br/&gt;
Indeed, Torvalds&amp;#39; post isn&amp;#39;t exactly pro-AI. He&amp;#39;s certainly not demanding anyone to use it, nor even really advocating for its use, and he acknowledges that it has been problematic for Linux &lt;a href=&quot;https://hothardware.com/news/playstation-3-emulator-team-rpcs3-tells-users-to-stop-flooding-github-with-ai-slop&quot;&gt;and free software&lt;/a&gt; in the past. His stance is made clear when he says &amp;quot;We&amp;#39;re not forcing anybody to use it, but I will very loudly ignore people who try to argue against other people from using it.&amp;quot; The physics of &amp;quot;very loudly ignoring&amp;quot; someone aside, the point is that anti-AI sentiment, especially that driven by ideology, is not welcome in the Linux Kernel project.&lt;br/&gt;&lt;br/&gt;
It&amp;#39;s important to understand some of the context here. There&amp;#39;s a relatively small but very noisy contingent of programmers who are also highly active politically, and the vast majority of this group are anti-AI ideologues. Linus has consistently resisted attempts to make kernel governance revolve around anything other than technical merit, and so he is understandably not keen to have this &lt;a href=&quot;https://hothardware.com/news/playstation-ceo-discusses-ai-in-game-development&quot;&gt;extremely American culture war&lt;/a&gt; imported into the very core of Linux. It&amp;#39;s not really about AI in the first place; it&amp;#39;s about ideology, tribalism, and political leverage, all advanced under the guise of &amp;quot;social justice.&amp;quot;&lt;br/&gt;&lt;br/&gt;&lt;div&gt;&lt;img src=&quot;data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&quot; alt=&quot;linus torvalds on ai in linux2&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;br/&gt;
Again, AI isn&amp;#39;t perfect; &lt;a href=&quot;https://hothardware.com/news/torvalds-tightens-linux-kernel-rules-to-reject-deluge-of-low-value-ai-fixes&quot;&gt;it has caused real problems&lt;/a&gt; for open-source projects. However, it&amp;#39;s also a legitimately powerful tool, and besides, human programmers submit plenty of crummy code and problematic patch requests without the help of AI. Torvalds acknowledges this by saying &amp;quot;anybody who points to the problems at AI had better be looking in the mirror and pointing at themselves at the same time. Because it&amp;#39;s not like natural intelligence is always all that great either.&amp;quot;&lt;br/&gt;&lt;br/&gt;
Ultimately the message is against holy wars and pro-technology. &lt;a href=&quot;https://lore.kernel.org/all/CAHk-%3Dwi4zC%2BZe8e%2Bp3tMv8TtG_80KzsZ1syL9anBtmEh5Z40vg@mail.gmail.com/&quot;&gt;Concluding his message&lt;/a&gt;, Torvalds specifically says &amp;quot;This is *NOT* some kind of &amp;#39;social warrior&amp;#39; project, never has been, and never will be. In the kernel community we do open source because it results in better technology, not because of religious reasons. And so we make decisions primarily based on technical merit.&amp;quot; It&amp;#39;s a clear response to ideologues who would seek to subvert the purity of the Linux Kernel project, and from my point of view, it&amp;#39;s heartening to see in a world where most organizations seem all too eager to bend the knee to exactly this sort of advocacy.&lt;br/&gt;&lt;br/&gt;&lt;em&gt;&lt;sub&gt;Top image by &lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Linus_Torvalds_at_the_Annual_Meeting_of_the_New_Champions_in_Tianjin,_China_2012.jpg&quot;&gt;World Economic Forum&lt;/a&gt; / &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;&gt;CC BY-SA 2.0&lt;/a&gt;&lt;/sub&gt;&lt;/em&gt;</content:encoded>
</item>
<item>
<title>Huawei HG8245H, can&#39;t read some system files</title>
<link>https://reverseengineering.stackexchange.com/questions/26670/huawei-hg8245h-cant-read-some-system-files</link>
<guid isPermaLink="false">Y-Mis5PjO4t_sVSEf9c4lwYP48m27yExcv3ODg==</guid>
<pubDate>Fri, 17 Jul 2026 00:00:49 +0000</pubDate>
<description>I have modem Echolife HG8245H (V3R016C10S150). I&#39;m using telnet to connect it. I need to read some files from this modem. There&#39;s a shell mode I can enter, but it is nerfed badly: SU_WAP&gt;shell BusyBox v1.18.4 (2016-10-11 19:35:35 CST) built-in shell (ash) Enter &#39;help&#39; for a list of built-in commands. profile close core dump WAP(Dopra Linux) # ? exit getcustominfo.sh restorehwmode.sh These are all commands I can do in this mode. There is another way to look at the directories: SU_WAP&gt;wap list ...</description>
<content:encoded>&lt;p&gt;I have modem Echolife HG8245H (V3R016C10S150). I&amp;#39;m using telnet to connect it. I need to read some files from this modem. There&amp;#39;s a shell mode I can enter, but it is nerfed badly:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;SU_WAP&amp;gt;shell BusyBox v1.18.4 (2016-10-11 19:35:35 CST) built-in shell (ash) Enter &amp;#39;help&amp;#39; for a list of built-in commands. profile close core dump WAP(Dopra Linux) # ? exit getcustominfo.sh restorehwmode.sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These are all commands I can do in this mode. There is another way to look at the directories:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;SU_WAP&amp;gt;wap list path / bin boot dev etc html lib libexec linuxrc mnt proc root sbin share sys tmp uer usr var&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It works like &amp;#39;ls&amp;#39;. But I can not read any file:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;SU_WAP&amp;gt;wap list path /var/wifi.txt /var/wifi.txt success!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Commands like &amp;#39;cat&amp;#39; aren&amp;#39;t working. Does anybody know is there any way to read these files if you&amp;#39;re connecting modem through telnet? Maybe this is not possible with this firmware?&lt;br/&gt; Thank you:)&lt;/p&gt;</content:encoded>
</item>
<item>
<title>We Built a New Editor. Want to Try It? – Simplenote</title>
<link>https://simplenote.com/2026/07/03/we-built-a-new-editor-want-to-try-it/</link>
<enclosure type="image/jpeg" length="0" url="https://i0.wp.com/simplenote.com/wp-content/uploads/2026/07/cleanshot-2026-07-03-at-16.38.35402x-e1783069318189.png?fit=1200%2C592&amp;ssl=1"></enclosure>
<guid isPermaLink="false">aogHaOUKxgLUp23E7uIcuIXFjNIcAvqjiw7FeA==</guid>
<pubDate>Thu, 16 Jul 2026 15:21:04 +0000</pubDate>
<description>A few months ago, Automattic launched Radical Speed Month: a company-wide sprint during which teams picked a passion project and built something real. Here at Simplenote, one of those projects focu…</description>
<content:encoded>&lt;figure&gt;
				&lt;img src=&quot;https://simplenote.com/wp-content/uploads/2026/07/cleanshot-2026-07-03-at-16.38.35402x-e1783069318189.png?w=1302&quot; alt=&quot;Simplenote WYSIWYG Markdown editor demo screenshot&quot; title=&quot;&quot;/&gt;			&lt;/figure&gt;&lt;div&gt;
		
&lt;p&gt;A few months ago, Automattic launched &lt;a href=&quot;https://www.linkedin.com/posts/radicalspeedmonth-share-7453472835886387200-mysj/&quot;&gt;&lt;strong&gt;Radical Speed Month&lt;/strong&gt;&lt;/a&gt;: a company-wide sprint during which teams picked a passion project and built something real. Here at Simplenote, one of those projects focused on the editor. Could we make Markdown feel more immediate in Simplenote? Still plain text at its core, but easier to read and write? The result is a &lt;strong&gt;“What You See Is What You Get” (WYSIWYG) Markdown editor prototype&lt;/strong&gt; for the Simplenote desktop app, and we’re ready for you to try it!&lt;/p&gt;



&lt;h3&gt;What we built&lt;/h3&gt;



&lt;p&gt;Simplenote isn’t changing what a note &lt;em&gt;is&lt;/em&gt;. Your notes are still Markdown (or plain text). They still sync everywhere. What’s new, however, is how writing &lt;em&gt;feels&lt;/em&gt; on desktop. Headings, bold, italic, strikethrough, and list markers appear styled inline as you type Markdown. **bold** becomes &lt;strong&gt;bold&lt;/strong&gt;, # heading becomes a large heading. Need help with Markdown syntax? The new toolbar is there to help.&lt;/p&gt;



&lt;p&gt;Now it’s your turn! &lt;strong&gt;Give us your feedback&lt;/strong&gt; and help us shape the future of the Simplenote editor.&lt;/p&gt;


&lt;div&gt;
&lt;figure&gt;&lt;a href=&quot;https://simplenote.com/wp-content/uploads/2026/07/cleanshot-2026-07-03-at-16.45.21.gif&quot;&gt;&lt;img src=&quot;https://simplenote.com/wp-content/uploads/2026/07/cleanshot-2026-07-03-at-16.45.21.gif?w=750&quot; alt=&quot;Markdown WYSIWYG Animated Demonstration&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;


&lt;h3&gt;Try the prototype&lt;/h3&gt;



&lt;p&gt;This build is available for &lt;strong&gt;Windows, macOS, and Linux&lt;/strong&gt; as a pre-release desktop download:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Automattic/simplenote-electron/releases/download/v2.27.2-md-editor-wysiwyg.1/Simplenote-win-2.27.2-md-editor-wysiwyg.1.exe&quot;&gt;Download for Windows (64-bit)&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://github.com/Automattic/simplenote-electron/releases/download/v2.27.2-md-editor-wysiwyg.1/Simplenote-macOS-2.27.2-md-editor-wysiwyg.1.dmg&quot;&gt;Download for macOS&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://github.com/Automattic/simplenote-electron/releases/download/v2.27.2-md-editor-wysiwyg.1/Simplenote-linux-2.27.2-md-editor-wysiwyg.1-x86_64.AppImage&quot;&gt;Download for Linux (AppImage)&lt;/a&gt; – (&lt;a href=&quot;https://github.com/Automattic/simplenote-electron/releases/download/v2.27.2-md-editor-wysiwyg.1/Simplenote-linux-2.27.2-md-editor-wysiwyg.1-arm64.AppImage&quot;&gt;arm64 AppImage&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Or browse all files on the &lt;a href=&quot;https://github.com/Automattic/simplenote-electron/releases/tag/v2.27.2-md-editor-wysiwyg.1&quot;&gt;GitHub release page&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;One app at a time:&lt;/strong&gt; Quit any open copy of Simplenote before installing or launching this build.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Returning to the official app:&lt;/strong&gt; Your notes stay in your account no matter which build you’re running. If you replaced your usual Simplenote install, you’ll be prompted to switch back when a new release is available — or simply reinstall the latest version anytime from &lt;a href=&quot;https://simplenote.com&quot;&gt;simplenote.com&lt;/a&gt;.&lt;/p&gt;



&lt;h3&gt;Tell us what you think&lt;/h3&gt;



&lt;p&gt;If this editor makes writing easier, we want to hear about it. If something doesn’t feel quite right, we want to hear about that too. Please drop us an email at &lt;a href=&quot;mailto:support@simplenote.com&quot;&gt;support@simplenote.com&lt;/a&gt;. &lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;h3&gt;Share this:&lt;/h3&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://simplenote.com/2026/07/03/we-built-a-new-editor-want-to-try-it/?share=twitter&quot;&gt;
				&lt;span&gt;Share on X (Opens in new window)&lt;/span&gt;
				&lt;span&gt;X&lt;/span&gt;
			&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://simplenote.com/2026/07/03/we-built-a-new-editor-want-to-try-it/?share=facebook&quot;&gt;
				&lt;span&gt;Share on Facebook (Opens in new window)&lt;/span&gt;
				&lt;span&gt;Facebook&lt;/span&gt;
			&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Like&lt;/span&gt;&lt;/span&gt; &lt;span&gt;Loading...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
	
&lt;/div&gt;&lt;/div&gt;	&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Patchless</title>
<link>https://patchless.natey.sh/</link>
<enclosure type="image/jpeg" length="0" url="https://patchless.natey.sh/patchless-og.png"></enclosure>
<guid isPermaLink="false">-RXqpFNuYV5v9mJMPqTVbbLl4qY4jDY-mAoTTA==</guid>
<pubDate>Thu, 16 Jul 2026 10:14:51 +0000</pubDate>
<description>Linux stable vulnerability commit monitor</description>
<content:encoded>&lt;p&gt;&lt;a href=&quot;https://lobste.rs/s/pfz6dj/filtering_engine_db_for_unpropagated&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content:encoded>
</item>
<item>
<title>TLS Certificate Validation on Linux · Ivan Tomica</title>
<link>https://www.tomica.net/blog/2026/07/tls-certificate-validation-on-linux/</link>
<guid isPermaLink="false">fMHFCY4FQxPmiX5C4GCWina1eF5Zh04JtyVpQQ==</guid>
<pubDate>Thu, 16 Jul 2026 01:11:13 +0000</pubDate>
<description>We all know the drill. You type https:// into the browser, a padlock shows up, and everyone collectively agrees not to think about what just happened. That works fine right up until the moment some application on your server starts throwing certificate verify failed while curl against the same endpoint works perfectly. Or the other way around. That’s usually the point where people discover that “the system trusts the certificate” is a much less well-defined statement than it sounds.</description>
<content:encoded>&lt;p&gt;We all know the drill. You type &lt;code&gt;https://&lt;/code&gt; into the browser, a padlock shows up, and everyone collectively agrees not to think about what just happened. That works fine right up until the moment some application on your server starts throwing &lt;code&gt;certificate verify failed&lt;/code&gt; while &lt;code&gt;curl&lt;/code&gt; against the same endpoint works perfectly. Or the other way around. That’s usually the point where people discover that “the system trusts the certificate” is a much less well-defined statement than it sounds.&lt;/p&gt;&lt;p&gt;So let’s unpack what actually happens when a program on a Linux system decides whether to trust a TLS certificate, and why two programs on the &lt;em&gt;same&lt;/em&gt; machine can happily disagree about it.&lt;/p&gt;&lt;h2&gt;What the server actually sends&lt;/h2&gt;&lt;p&gt;During the TLS handshake, the server doesn’t just send its certificate. It sends (or at least it should send) a whole chain:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;leaf certificate&lt;/strong&gt;, issued for the actual hostname&lt;/li&gt;
&lt;li&gt;one or more &lt;strong&gt;intermediate certificates&lt;/strong&gt;, which issued the leaf&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;What it does &lt;em&gt;not&lt;/em&gt; send is the root certificate. There would be no point. A root the client doesn’t already have is worthless, since the entire trust model rests on the client having its own local copy of the roots it considers trustworthy. A root certificate arriving over the network from the very party you’re trying to verify would be about as convincing as an email signature saying “definitely not a scammer”.&lt;/p&gt;&lt;p&gt;The client’s job is then to build a path from the leaf it received, through the intermediates, up to a root it already knows and trusts. Each certificate in the chain is signed by the next one up, so the client verifies signatures link by link until it lands on something from its local trust store. If it can’t complete that path (missing intermediate, unknown root, whatever), the connection is refused.&lt;/p&gt;&lt;p&gt;That “missing intermediate” case deserves a special mention because it’s a classic. A misconfigured server that sends only the leaf will work fine in browsers (they cache intermediates seen elsewhere and can even fetch them on demand) and fail miserably with OpenSSL-based tools, which do no such fetching. If you’ve ever had a site that “works in Chrome but not in curl”, there’s a very good chance this was it.&lt;/p&gt;&lt;p&gt;Chain building is only part of the story though. Along the way the client also checks:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;validity dates&lt;/strong&gt; - is the certificate expired, or not yet valid&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;hostname&lt;/strong&gt; - does the name you’re connecting to appear in the certificate’s Subject Alternative Names&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;key usage constraints&lt;/strong&gt; - is the intermediate actually allowed to issue certificates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revocation&lt;/strong&gt; - in theory via CRL or OCSP, in practice this one gets skipped or soft-failed far more often than anyone in the industry likes to admit&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All of that is mechanical. The interesting question is the last step: what exactly is that “local trust store” the chain has to terminate in?&lt;/p&gt;&lt;h2&gt;The system trust store&lt;/h2&gt;&lt;p&gt;On Linux, root certificates are just files on disk. There’s no TPM magic, no registry, nothing exotic. Just a directory full of PEM-encoded certificates and a couple of symlink/concatenation tricks on top.&lt;/p&gt;&lt;p&gt;The certificates themselves typically come from the distribution’s &lt;code&gt;ca-certificates&lt;/code&gt; package, which in turn repackages the Mozilla root program’s list. So when people say “the system trusts this CA”, what they really mean is “Mozilla trusts this CA, Debian repackaged that decision, and my system installed it”. A fun chain of custody to think about, but it works remarkably well.&lt;/p&gt;&lt;p&gt;Where things get less uniform is &lt;em&gt;where&lt;/em&gt; those files live and how you add your own. Every distribution family has its own idea:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Debian-based systems keep the bundle in &lt;code&gt;/etc/ssl/certs/ca-certificates.crt&lt;/code&gt;, and you add local CAs by dropping them into &lt;code&gt;/usr/local/share/ca-certificates/&lt;/code&gt; and running &lt;code&gt;update-ca-certificates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Red Hat-based systems use &lt;code&gt;/etc/pki/ca-trust/&lt;/code&gt;, you drop files into &lt;code&gt;/etc/pki/ca-trust/source/anchors/&lt;/code&gt; and run &lt;code&gt;update-ca-trust&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;and then there’s everyone else, each with a slightly different path and update command&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The update command’s job is to take all the sources (the distro bundle plus your local additions) and regenerate the various formats applications expect: a single concatenated PEM bundle, a hashed directory for OpenSSL’s lookup, sometimes a Java keystore too. Modern distributions increasingly funnel all of this through &lt;code&gt;p11-kit&lt;/code&gt;, which acts as a central broker so that different crypto libraries can share one trust source. Increasingly. Not universally. Remember that word, it’s about to matter.&lt;/p&gt;&lt;h2&gt;Here’s where it falls apart&lt;/h2&gt;&lt;p&gt;The dirty secret is that “the system trust store” is a gentleman’s agreement, not an enforcement mechanism. Nothing in the kernel or anywhere else &lt;em&gt;forces&lt;/em&gt; an application to use it. TLS validation happens entirely in userspace, inside whatever TLS library the application happens to link against, and that library reads whatever trust source it was configured to read.&lt;/p&gt;&lt;p&gt;And applications, as it turns out, love bringing their own.&lt;/p&gt;&lt;p&gt;The TLS library landscape alone already fragments things. OpenSSL, GnuTLS, and NSS each have their own default lookup paths, which distros patch to point at the system store with varying degrees of consistency. But the real fun starts one layer up:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java&lt;/strong&gt; ships its own keystore (&lt;code&gt;cacerts&lt;/code&gt;), managed with its own tool (&lt;code&gt;keytool&lt;/code&gt;), in its own format, completely oblivious to anything in &lt;code&gt;/etc/ssl&lt;/code&gt;. Some distributions wire it up to the system store, some don’t, and the JVM you downloaded as a tarball certainly doesn’t&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node.js&lt;/strong&gt; compiles Mozilla’s root list &lt;em&gt;into the binary&lt;/em&gt;. The certificates your Node application trusts were decided when that Node version was built&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; - the standard library uses OpenSSL’s defaults, which usually means the system store. But the popular &lt;code&gt;requests&lt;/code&gt; library pulls in &lt;code&gt;certifi&lt;/code&gt;, which is Mozilla’s bundle shipped as a pip package. So a single Python process can contain two different trust stores depending on which import a given code path uses&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browsers&lt;/strong&gt; famously do their own thing entirely, Firefox with NSS and its own root program, Chrome nowadays with its own root store as well&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt; reads the system store, but like nearly everything else it honors &lt;code&gt;SSL_CERT_FILE&lt;/code&gt; and &lt;code&gt;SSL_CERT_DIR&lt;/code&gt; overrides, as do OpenSSL-based tools, joined by app-specific variables like &lt;code&gt;NODE_EXTRA_CA_CERTS&lt;/code&gt; and &lt;code&gt;REQUESTS_CA_BUNDLE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;From the application vendor’s perspective this is all perfectly rational. Shipping your own trust store means consistent behavior across every platform, no dependency on the distro getting things right, no surprises from whatever the local admin did to &lt;code&gt;/etc/ssl&lt;/code&gt;. Java behaves the same on Linux, macOS, FreeBSD, and that one Windows machine nobody wants to touch, precisely &lt;em&gt;because&lt;/em&gt; it ignores all of them equally.&lt;/p&gt;&lt;p&gt;From the sysadmin’s perspective, it means the question “does this machine trust my CA?” has no single answer. The machine doesn’t trust anything. Applications do, each in their own way.&lt;/p&gt;&lt;h2&gt;The private CA obstacle course&lt;/h2&gt;&lt;p&gt;Where this bites hardest is internal infrastructure. You run your own CA (for internal services, a MitM-ing corporate proxy, a homelab, doesn’t matter) and now you need your systems to trust it. The naive expectation is one step: add the CA to the system store, run the update command, done.&lt;/p&gt;&lt;p&gt;The actual experience tends to be more of a scavenger hunt:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;add the CA to the system store - &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt; and most C-linked things are now happy&lt;/li&gt;
&lt;li&gt;discover the Java service still fails, &lt;code&gt;keytool -importcert&lt;/code&gt; into its &lt;code&gt;cacerts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;discover the Node service still fails, set &lt;code&gt;NODE_EXTRA_CA_CERTS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;discover the Python service still fails because &lt;code&gt;certifi&lt;/code&gt;, set &lt;code&gt;REQUESTS_CA_BUNDLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;discover some container image fails because it has its &lt;em&gt;own&lt;/em&gt; &lt;code&gt;/etc/ssl&lt;/code&gt; inside, completely separate from the host’s&lt;/li&gt;
&lt;li&gt;repeat for every runtime, tool, and container you’ll ever deploy&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;That last point about containers is worth an extra sentence: an application in a container brings its own filesystem, which means its own trust store, which means all of the above nested one level deeper. Your host trusts the CA just fine, but the process inside the container is validating against the &lt;code&gt;/etc/ssl&lt;/code&gt; that came with the image, blissfully unaware of anything you did on the host. The usual fix is to mount the host’s CA bundle over the container’s copy, either as a read-only bind mount or, in Kubernetes, as a volume pointed at the right path.&lt;/p&gt;&lt;p&gt;None of this is broken, strictly speaking. Every one of those applications is behaving exactly as designed. It’s just that “as designed” was decided by a dozen different projects with a dozen different philosophies, and you get to integrate the result.&lt;/p&gt;&lt;p&gt;There’s also a legitimate flip side: an application controlling its own trust chain isn’t only an annoyance, it can be a feature. Pinning, meaning trusting only your specific CA, or even one specific certificate, instead of the two-hundred-ish public roots, dramatically shrinks the attack surface for that one connection. A backend service that talks exclusively to your internal API has no business trusting every certificate authority on the planet. The same mechanism that makes private CAs annoying to roll out is what makes this kind of hardening possible at all.&lt;/p&gt;&lt;p&gt;The trust model itself is fine. Chain building, signatures, local roots, all of it is well-designed and battle-tested. What Linux doesn’t have is a single enforcement point for it, and honestly, it never claimed to. “The system trust store” is a default, a convention that most things follow and nothing has to.&lt;/p&gt;&lt;p&gt;So the next time an application refuses a certificate that every other tool on the box accepts, skip the stage of doubting your sanity and go straight to the useful question: &lt;em&gt;which trust store is this thing actually reading?&lt;/em&gt;&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Is Denuvo&#39;s Dominance Finally Beginning to Crack?</title>
<link>https://gardinerbryant.com/is-denuvos-dominance-finally-beginning-to-crack/</link>
<enclosure type="image/jpeg" length="0" url="https://gardinerbryant.com/content/images/2026/07/Denuvo.jpg"></enclosure>
<guid isPermaLink="false">2UpQvB7vnfklnky-5MBzi82ZEsm4tEsUpninDg==</guid>
<pubDate>Wed, 15 Jul 2026 22:21:49 +0000</pubDate>
<description>A new hypervisor-based bypass method, demonstrated extensively within the Linux gaming community using Proton and Wine, has emerged</description>
<content:encoded>&lt;div&gt;
            &lt;/div&gt;&lt;div&gt;&lt;div&gt;🚧&lt;/div&gt;&lt;div&gt;Editor&amp;#39;s note: we have not verified the details or the implementation of this workaround. If you chose to try it, you do so at your own risk!&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For nearly a decade, Denuvo has been the PC gaming industry&amp;#39;s most formidable form of anti-tamper protection. Publishers have relied on it to safeguard high-profile launches, while cracking groups have increasingly struggled to keep pace. In recent years, successful bypasses have become so rare that many viewed Denuvo as effectively unbeatable. It looks like that perception may &lt;em&gt;finally&lt;/em&gt; be starting to change.&lt;/p&gt;&lt;p&gt;This week, members of the CrackWatch community declared &amp;quot;the year of the Linux desktop&amp;quot; after a new Linux-based method emerged that can launch an increasing number of Denuvo-protected games without triggering the DRM. Activity on certain forums has accelerated alongside the announcement, with users documenting compatibility reports and testing additional titles as the technique continues to evolve.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack15.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack13.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;What makes this development particularly unusual is the role Linux gaming has played in the bypass. Rather than removing Denuvo from a game&amp;#39;s executable or distributing modified files, the new approach combines hypervisor techniques with Linux compatibility layers such as Proton and Wine. Running Windows games through Proton changes the execution environment, while the hypervisor method appears to take advantage of those differences to bypass Denuvo&amp;#39;s protections without producing a traditional crack. Exactly why it works is still being investigated by the community, but the result is a growing list of games that can be launched under Linux where the same approach does not work on native Windows installations.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack12.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack6.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack5.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack2.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/crack1.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;That distinction is important. Proton itself is not a Denuvo bypass, nor did Linux originate the underlying hypervisor technique. Instead, Linux has become an unexpected platform where the method has proven effective, giving the Linux gaming community an unusually prominent role in what is shaping up to be one of the biggest challenges Denuvo has faced in years.&lt;/p&gt;&lt;p&gt;Whether this proves to be a short-lived loophole or the beginning of a broader shift remains to be seen. Denuvo has weathered numerous challenges throughout its history, and its developers have consistently updated the technology in response to new attack methods.&lt;/p&gt;&lt;p&gt;Even so, this is arguably the strongest challenge the DRM has faced in years. Beyond the piracy discussion, Denuvo has long been a flashpoint in debates surrounding game preservation, offline ownership, Linux gaming, and the long-term accessibility of purchased PC titles. If this Linux-based approach continues to mature, it could mark the first real sign that the industry&amp;#39;s most dominant DRM solution is no longer as untouchable as it once seemed.&lt;/p&gt;&lt;div&gt;&lt;div&gt;ℹ️&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;em&gt;Traditional Denuvo cracks modify or remove the DRM from a game&amp;#39;s executable. The new method instead focuses on the environment the game runs in. By combining virtualization (a hypervisor) with Linux compatibility layers like Proton, it can allow some protected games to run without altering the game&amp;#39;s files. Because of this, many in the community describe it as a bypass rather than a conventional crack.&lt;/em&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;div&gt;
            Read more: &lt;a href=&quot;https://gardinerbryant.com/tag/gaming/&quot;&gt;Gaming&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/linux-gaming/&quot;&gt;Linux Gaming&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/linux/&quot;&gt;Linux&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/news/&quot;&gt;News&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/pc-gaming/&quot;&gt;PC Gaming&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/proton/&quot;&gt;proton&lt;/a&gt;, &lt;a href=&quot;https://gardinerbryant.com/tag/steam/&quot;&gt;Steam&lt;/a&gt;
        &lt;/div&gt;&lt;div&gt;
            &lt;a href=&quot;https://www.google.com/preferences/source?q=gardinerbryant.com&quot;&gt;
            With Google recently announcing they&amp;#39;re &lt;em&gt;dismantling their search platform&lt;/em&gt;, there&amp;#39;s 
            no better time to add &lt;strong&gt;The Bryant Review&lt;/strong&gt; as one of your preferred sources.
            &lt;/a&gt;
        &lt;/div&gt;&lt;div&gt;
                    &lt;img src=&quot;https://gardinerbryant.com/content/images/size/w320/2025/10/IMG20230222140721.jpg&quot; alt=&quot;dash&quot; title=&quot;&quot;/&gt;
                &lt;h2&gt;About the Author:&lt;/h2&gt;
                &lt;h3&gt;
                    dash
                &lt;/h3&gt;
                    &lt;p&gt;Passionate about retro gaming, game preservation, open-source software, and retro handhelds. I tell the stories behind games, hardware, and the people building them. Usually testing a new handheld, using Linux or F-Droid, or replaying a classic.&lt;/p&gt;
                &lt;footer&gt;
                    &lt;div&gt;
                            &lt;a href=&quot;https://mastodon.social/@flwwhtrbt&quot;&gt;&lt;/a&gt;
                        &lt;a href=&quot;https://gardinerbryant.com/author/dash/&quot;&gt;More from dash&lt;/a&gt;
                    &lt;/div&gt;
                &lt;/footer&gt;
            &lt;/div&gt;</content:encoded>
</item>
<item>
<title>aol/trusty-boot-key: Set up a flash drive to &quot;multi-boot&quot; OS images from a menu. - Codeberg.org</title>
<link>https://codeberg.org/aol/trusty-boot-key</link>
<enclosure type="image/jpeg" length="0" url="https://codeberg.org/aol/trusty-boot-key/-/summary-card"></enclosure>
<guid isPermaLink="false">Vuy839NsunQA5adACABBeFrKK_8Zy7oJZLpW3g==</guid>
<pubDate>Wed, 15 Jul 2026 00:39:33 +0000</pubDate>
<description>Set up a flash drive to &quot;multi-boot&quot; OS images from a menu.</description>
<content:encoded>&lt;h1&gt;Trusty Boot Key - TBK&lt;/h1&gt;&lt;p&gt;&lt;em&gt;&amp;quot;Submitted for your approval, a Trusty Boot Key—with all GPL¹ code…&amp;quot;—Rod Serling&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Need a &amp;quot;trusty boot key&amp;quot; to load operating systems?
A USB flash-drive for troubleshooting and experimentation?
Read on.&lt;/p&gt;&lt;p&gt;
&lt;img src=&quot;https://codeberg.org/aol/trusty-boot-key/media/branch/main/images/theme-simple.png&quot; alt=&quot;GRUB Theme Preview&quot; title=&quot;&quot;/&gt;  
&lt;img src=&quot;https://codeberg.org/aol/trusty-boot-key/media/branch/main/images/theme-trusty.jpg&quot; alt=&quot;GRUB Theme Preview&quot; title=&quot;&quot;/&gt;
&lt;/p&gt;&lt;p&gt;The theme and fonts still need work, but you get the idea.
Other themes are easy to install as well.&lt;/p&gt;&lt;p&gt;[1] If you&amp;#39;re one of those folks that worries about the GPL—no need.
This is an application and has no affect on other projects.&lt;/p&gt;&lt;h2&gt;Rationale&lt;/h2&gt;&lt;p&gt;We were quite impressed with the ease of use of Ventoy,
but dismayed by its
&lt;a href=&quot;https://news.ycombinator.com/item?id=44810281&quot;&gt;security posture&lt;/a&gt;,
especially in light of the not-so recent
&lt;a href=&quot;https://en.wikipedia.org/wiki/XZ_Utils_backdoor&quot;&gt;xz backdoor&lt;/a&gt;
fiasco.
No bad news as of yet,
but its hard to imagine a better way to install low-level malware across the
globe. :-/&lt;/p&gt;&lt;p&gt;While looking around for a &amp;quot;Safe-Toy&amp;quot; alternative,
we found a number of projects attempting to bring comparable ease of use to a
GRUB multi-boot system on a similar removable drive.&lt;/p&gt;&lt;p&gt;But the projects were hard to grok.
Complicated menus,
clunky, redundant code,
abandoned/archived repos,
and tons of info about BIOS this, MBR, GRUB 1.0, and 16-bit that…&lt;/p&gt;&lt;p&gt;Huh,
what is this, 1996?  Haha.
(These were already hitting their limits during the Clinton Administration.)&lt;/p&gt;&lt;h2&gt;Support&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;UEFI (firmware)&lt;/li&gt;
&lt;li&gt;GPT partition table&lt;/li&gt;
&lt;li&gt;amd64 architecture&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;That&amp;#39;s it.
A.k.a. a modern P.C.
To simplify development and docs we&amp;#39;ve removed everything related to &lt;em&gt;ancient&lt;/em&gt;
BIOS, MBR, and &amp;lt;= 32-bit architectures.
Yes—it&amp;#39;s been about &lt;em&gt;twenty years&lt;/em&gt; since we had one of those in the house.
There&amp;#39;s still a late 2013 MBP running acceptably here,
with UEFI and 64-bit support,
currently pushing thirteen years old.&lt;/p&gt;&lt;p&gt;If you&amp;#39;re a vintage computing enthusiast on a souped-up 486/DX9,
fine—this project isn&amp;#39;t for you.
Otherwise,
there are likely free computers offered thru your local craigstlist meeting the
~2010 specs listed above,
sometimes even left on a sidewalk or trash-bins in larger cities.
If you&amp;#39;re willing to spend upwards of perhaps… ~$250?
One could probably find something more formidable from the last decade.&lt;/p&gt;&lt;h3&gt;ARM, R-V?&lt;/h3&gt;&lt;p&gt;While it&amp;#39;s possible we could support ARM64 or even RISC-V systems in the future,
there are none of those laying around handy at the moment.
Oh wait, there is an RPi 4 in a drawer nearby…
Unsure how to get started on that however,
and there&amp;#39;s still a lot to do.&lt;/p&gt;&lt;h3&gt;Operating Systems&lt;/h3&gt;&lt;p&gt;Everything Linux seems to work,
although on older images you may have to write some kernel parameters into a
support file.
We&amp;#39;ve done that work for loopback.cfg-compatibles and a few very popular other
distros,
but will need your help for the more obscure ones.
See contributing below.&lt;/p&gt;&lt;h4&gt;Windows, BSD?&lt;/h4&gt;&lt;p&gt;These aren&amp;#39;t able to work from a .iso loopback device.
Some folks say that creating a partition and unpacking the .iso there works.&lt;/p&gt;&lt;p&gt;Update: Tried Windows 10 and the installer starts up, although with an error.
See the customization section later on.&lt;/p&gt;&lt;h2&gt;How does it work?&lt;/h2&gt;&lt;p&gt;First, we&amp;#39;ll help you create a removable drive with a layout like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;╭───────┬──────────────────╮
│  ESP  │  Data Zone ---&amp;gt;  │
╰───────┴──────────────────╯&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What you see above is a disk diagram,
cut in two (or more) parts.
(Well, a unit of storage perhaps—they
don&amp;#39;t look like frisbees internally any longer.)&lt;/p&gt;&lt;p&gt;We can divide a storage device into sections according to function,
each optimized for its needs.
In this situation each section is called a &amp;quot;partition,&amp;quot;
and nearly always contains a &amp;quot;file-system&amp;quot; to catalog the files.
These different filesystems have tradeoffs of their own,
typically relating to both functionality and compatibility.&lt;/p&gt;&lt;p&gt;The first partition above is the &amp;quot;E.S.P.,&amp;quot;
a recursive acronym that expands to the
&lt;a href=&quot;https://en.wikipedia.org/wiki/EFI_system_partition&quot;&gt;&amp;quot;E.F.I&amp;quot; System Partition&lt;/a&gt;
standard.
It uses the venerable and simplistic
&lt;a href=&quot;https://en.wikipedia.org/wiki/File_Allocation_Table&quot;&gt;FAT filesystem&lt;/a&gt;,
that just about any operating system since the 80s can read.
This is a standard for boot partitions that gives much more flexibility than
the old-fashioned boot sector.&lt;/p&gt;&lt;p&gt;We&amp;#39;ll help you create the partitions and install &amp;quot;GRUB&amp;quot; up in there.
That is GNU GRUB,
a slender operating system masquerading as a boot loader.
Interesting in that we thought we done with it,
moving several desktops to systemd-boot in recent years.
UEFI machines generally don&amp;#39;t need all that functionality any more,
it comes standard.
But the flexibility of ol&amp;#39; grub here is of great benefit to mounting and
running .iso files for a &amp;quot;trusty boot key.&amp;quot;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;quot;High-way to the data zone…&amp;quot;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;The second partition should be much larger and where you&amp;#39;re gonna drop those
&lt;em&gt;phat eye-soes&lt;/em&gt; or
&lt;a href=&quot;https://en.wikipedia.org/wiki/Optical_disc_image&quot;&gt;&amp;quot;boot images&amp;quot;&lt;/a&gt;,
in other words.
These might load a number of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Operating_system&quot;&gt;operating systems&lt;/a&gt;
temporarily as well as for permanent installation.
Supported binaries (think memtest86) and &lt;code&gt;.efi&lt;/code&gt; files should work as well.&lt;/p&gt;&lt;p&gt;Currently,
we are using the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Ext4&quot;&gt;ext4&lt;/a&gt;
filesystem for the data partition.
This is a tough one to decide on,
as each of the main choices has significant drawbacks:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FAT32 - most compatible,
but no files larger than 4GB,
ruling out many .iso files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exfat - very compatible,
though the Ubuntu family doesn&amp;#39;t support booting from it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UDF - widely compatible,
though obscure and often forgotten.
The Bluehat family doesn&amp;#39;t support booting from it.
No Apple support &lt;em&gt;inside&lt;/em&gt; a partition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ext4 - compatible with all Linux (except debian netinst),
permissions a minor annoyance on a removable drive.
Not typically supported elsewhere.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;It seemed that
&lt;a href=&quot;https://en.wikipedia.org/wiki/ExFAT&quot;&gt;exfat&lt;/a&gt;
was the best choice at first,
but as mentioned the Ubuntu family doesn&amp;#39;t support booting from it.
Ext4 is a good choice for a Linux-centric user,
but you may want to change it back to exfat if you&amp;#39;ll be using it often with
Windows machines or Macs.
(See the &amp;quot;customization&amp;quot; section later on for instructions.)&lt;/p&gt;&lt;p&gt;(There is a third optional partition however,
so one could pick their two favorites if necessary.)&lt;/p&gt;&lt;h2&gt;Install&lt;/h2&gt;&lt;p&gt;This project should be currently considered BETA quality.
However,
there&amp;#39;s been a lot of work put in to make these scripts robust and avoid
errors to the extent Bash and grub-script allows—including
the use of shellcheck,
defensive programming,
extensive error checking and avoidance,
and plenty of testing.&lt;/p&gt;&lt;p&gt;There still could be an issue or two lurking however—the
code has been changing—no
warranty expressed or implied.
Recommend starting with a throwaway key,
and reading everything the installer below tells you closely.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Get TBK:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Near the top right of the page ⤴, you&amp;#39;ll see a git repo URL to clone from:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;git clone ssh://git@codeberg.org/aol/trusty-boot-key.git
    # or
    git clone ssh://git@codeberg.org/aol/trusty-boot-key.git&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;No git?
Well, next to that is a link with a [⋯] icon,
click on that to download an archive from the menu,
and then unpack it.&lt;/p&gt;&lt;p&gt;The scripts inside currently need these packages to run,
it&amp;#39;s best to install them beforehand:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;adwaita-mono-fonts - perhaps adwaita-fonts&lt;/li&gt;
&lt;li&gt;dosfstools&lt;/li&gt;
&lt;li&gt;grub2 grub2-efi-x64-modules - may be just grub in your distro&lt;/li&gt;
&lt;li&gt;parted&lt;/li&gt;
&lt;li&gt;udevadm - from systemd so probably have it&lt;/li&gt;
&lt;li&gt;udisks2&lt;/li&gt;
&lt;li&gt;maybe exfatprogs ntfsprogs, etc for other filesystems.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;It&amp;#39;s also a good idea to put yourself in the disks group,
so you don&amp;#39;t have to run sudo for the update script:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;sudo usermod -aG disk $USER
    # You can log out and back in to reload groups or run:
    exec su -l $USER&lt;/code&gt;&lt;/pre&gt;&lt;details&gt;&lt;summary&gt; &lt;b&gt;About Linux Device Names:&lt;/b&gt; &lt;/summary&gt;
&lt;p&gt;Linux removable disk device names have the format: &lt;code&gt;/dev/sdXN&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This means in the &lt;code&gt;/dev/&lt;/code&gt; device folder there&amp;#39;s a file where the first part of
the name is &lt;code&gt;sd&lt;/code&gt;,
which stood for &amp;quot;SCSI disks&amp;quot; in the old days.
Then another lower-case letter for the particular drive (here X),
and an optional partition number at the end (here N).
i.e.:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;/dev/sda    # whole device
    /dev/sda1   # first part&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The GNOME Disks, GParted, or KDE partition manager are helpful to see what is
connected to your system.
The first one is useful while installing TBK,
in that it reacts to changes happening live as you work,
allowing a birds-eye view.&lt;/p&gt;
&lt;/details&gt;&lt;p&gt;&lt;strong&gt;To install to the drive itself:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Beware!
Setup-drive.sh will &lt;em&gt;carve up and format your disk.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Note: The &lt;code&gt;X&lt;/code&gt; below represents a removable drive,
likely &lt;code&gt;a&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt;,
but potentially a later letter.
Do not give a partition number at the end—this one wants the whole device:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;cd ./trusty-boot-key  # this repo

    ./setup-drive.sh DEVICE  # aka /dev/sdX  - no number&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then follow instructions,
which is basically to hit the &amp;quot;y&amp;quot; key and hit ENTER several times.&lt;/p&gt;&lt;p&gt;If successful,
the setup-drive script will do the full grub-update steps mentioned below.
So if you went through that,
no need to do it again below.
(Good idea to read however.)&lt;/p&gt;&lt;h2&gt;Update GRUB and/or Menus&lt;/h2&gt;&lt;p&gt;To update the config files there is another convenience script.&lt;/p&gt;&lt;p&gt;Note: This one wants to update the ESP,
so do give a partition number at the end—which should be &lt;code&gt;1&lt;/code&gt;.
&lt;code&gt;X&lt;/code&gt; will be the same lower letter of the alphabet used above:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;./update-tbk.sh DEVICE_NUM  # aka /dev/sdX1 - include part. num 1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;An update will be needed if you&amp;#39;ve done a &lt;code&gt;git pull&lt;/code&gt; for the latest version of
TBK,
updated the config file,
or you&amp;#39;ve written some custom &amp;quot;grub script&amp;quot; yourself.&lt;/p&gt;&lt;p&gt;On rarer occasions you may want to rebuild and upgrade grub itself or the font
it uses.
Adding a module as a built-in requires this,
and external module additions are conveniently installed as well:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;./update-tbk.sh -g DEVICE_NUM  # aka /dev/sdaN&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Use&lt;/h2&gt;&lt;p&gt;When setup is done,
drop some images into the &lt;code&gt;os-images&lt;/code&gt; folder
(of the second partition of the removable drive),
pop it in the target,
and restart!
You may have to hit &lt;kbd&gt;F12&lt;/kbd&gt; at startup time or another key to select the
boot drive.
A common firmware boot-manager hot key—consult your system documentation.&lt;/p&gt;&lt;p&gt;Secure boot—not supported yet!
Not sure that we will as it&amp;#39;s a pain in the rear.
Can you help?&lt;/p&gt;&lt;h3&gt;Sorting the OS Images Menu&lt;/h3&gt;&lt;p&gt;Despite excessive functionality in other areas,
GRUB is only able to sort menu entries though some very hacked-up grub script,
and just barely.
We were able to implement a bubble sort,
though there is no list or array type,
so item-swap is done through string operations.
Very low performance!
Not been a problem so far with a dozen images or so.
Twenty might be doable on a fast machine?
Dunno, we&amp;#39;ll see how that plays out.
For this reason,
sort can be turned off for now,
see below.&lt;/p&gt;&lt;p&gt;If one moves the files off the drive and then returns them the operation
typically will be performed in alphabetical order,
meaning they&amp;#39;ll be sorted on disk.
If not,
try rsync.
This should speed up the sorting performance as well.
Better yet,
copy them manually in the order of use.
e.g. most used image copied first,
second second etc.
Then turn off sorting.&lt;/p&gt;&lt;h3&gt;Customization&lt;/h3&gt;&lt;p&gt;You can easily place custom entries into the menu by placing grub-script into a
file at the following location:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;$prefix/custom.cfg&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Prefix is grub-speak for the main &lt;code&gt;grub2&lt;/code&gt; folder.
In this case,
at the root of the ESP partition of your removable drive.
The first and smaller partition.&lt;/p&gt;&lt;p&gt;If this file is found, the contents inside will be evaluated.
Make sure it is syntactically correct or it will break things afterward.
Starting very simply and building from there is the best way.&lt;/p&gt;&lt;h4&gt;_config.sh&lt;/h4&gt;&lt;p&gt;One can also edit the &lt;code&gt;_config.sh&lt;/code&gt; file in the repo when ready to get serious
with customization.
The default localization for example,
(currently limited to a few western languages due to font restrictions).&lt;/p&gt;&lt;p&gt;You can also add additional grub modules,
change labels and the theme,
the size of the first partition,
and even the filesystem of the second (or third!) partition,
among other things.&lt;/p&gt;&lt;h4&gt;Themes&lt;/h4&gt;&lt;p&gt;There are three levels of quality.
A VGA-style text-mode interface is available in a pinch with the Escape key
pressed at early boot time.
Called &amp;#39;&amp;#39; (none) in &lt;code&gt;_config.sh&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;We&amp;#39;re using a simple theme by default,
which has HD resolution,
a unicode font,
and some color.&lt;/p&gt;&lt;p&gt;The graphical version included is a lightly-modified Slaze theme by
&lt;a href=&quot;https://github.com/adi1090x/uGRUB&quot;&gt;adi1090x/uGRUB&lt;/a&gt;.
Choose in &lt;code&gt;_config.sh&lt;/code&gt; and remember to run update with the &lt;code&gt;-g&lt;/code&gt; option once to
build the grub theme modules and install them:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;./update-tbk.sh -g /dev/sdX1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Themes then need to be copied to &lt;code&gt;/grub2/themes/$THEME_NAME&lt;/code&gt; folders.
The theme file currently must be named &lt;code&gt;theme.txt&lt;/code&gt;.&lt;/p&gt;&lt;h4&gt;Windows&lt;/h4&gt;&lt;p&gt;Not currently working.
It loads but install fails with a &amp;quot;Needs media driver error.&amp;quot;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;What we tried…&lt;/summary&gt;
Condolences—good tech, unethical management,
and we understand some folks are trapped.
The .iso is a no-go however,
so here&amp;#39;s how to (not-quite) get it working with TBK.
&lt;p&gt;Now that you understand &lt;code&gt;_config.sh&lt;/code&gt; and &lt;code&gt;custom.cfg&lt;/code&gt;,
you&amp;#39;ll want to edit _config and choose a filesystem or two,
depending if you are a dabbler or a devotee…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dabbler:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Recommend making a third partition. Fat32 or exfat is probably easiest,
we also tried NTFS with compression enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Find &lt;code&gt;VOL2_END&lt;/code&gt; and change it to &lt;code&gt;80%&lt;/code&gt;, &lt;code&gt;$SIZE - 10GB&lt;/code&gt;,
or whatever leaves enough space for the .iso contents and your needs.
Select the filesystems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let &lt;code&gt;setup-drive.sh&lt;/code&gt; carve up and format the disk.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unpack the .iso into the third partition.
(7zip can handle as well if your mounter is not working.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy &lt;code&gt;./grub/examples/windows.cfg&lt;/code&gt; to &lt;code&gt;grub/custom.cfg&lt;/code&gt;,
edit/augment as desired.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;./update-tbk.sh DEVICE_NUM&lt;/code&gt;,
use &lt;code&gt;-g&lt;/code&gt; also &lt;em&gt;only&lt;/em&gt; if you&amp;#39;ve changed the module list/font after setup.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boot and load the TBK menu.
Load ntfs and/or ntfscomp from the Utils menu first if need be.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Devotee:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Consider one big second partition with a &amp;quot;native&amp;quot; filesystem.&lt;/p&gt;
&lt;p&gt;(Windows may not install from a folder.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Move the ntfs modules to the &lt;code&gt;_GRUB_BUILTINS&lt;/code&gt; list as you will likely be
using them often,
to avoid having to load manually every time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Was not able to get this to work and pointed to:
&lt;a href=&quot;https://askubuntu.com/questions/1227291/grub-boot-from-windows-iso/1525482&quot;&gt;https://askubuntu.com/questions/1227291/grub-boot-from-windows-iso/1525482&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Might work for you.&lt;/p&gt;
&lt;/details&gt;&lt;h4&gt;FreeBSD&lt;/h4&gt;&lt;p&gt;We understand the process is quite likely similar to the Windows section above,
substituting UFS2 or ZFS for NTFS.
Haven&amp;#39;t yet tried it.
Let us know if it works.&lt;/p&gt;&lt;h2&gt;Help and Utils menus&lt;/h2&gt;&lt;p&gt;There&amp;#39;s a help menu that has a few useful entries for someone not that familiar
with GRUB or PC technology in general,
but is interested in learning.&lt;/p&gt;&lt;p&gt;Support modules,
such as a serial console or additional filesystem support
can be loaded as well,
all from the Utilities and Drivers menu.&lt;/p&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;&lt;p&gt;By default this starts up in graphics mode at 1920x1080 resolution with
and a medium-large font.
Which should be the bare minimum these days.
However,
maybe you&amp;#39;re in a pinch,
hacking on a machine in the closet with a relic of a monitor and that&amp;#39;s
not gonna work.&lt;/p&gt;&lt;p&gt;Well,
at startup up you can hold down the -shift- key to skip the graphics term and
use the standard monochrome (GOP? VGA?) console instead.
(One sacrifice we make to the ancients.)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; that functionality with the keystatus --shift key doesn&amp;#39;t seem to
work on our EDK2 machine.
So trying sleep,
and you&amp;#39;ll need to hit the &lt;strong&gt;Escape&lt;/strong&gt; key instead,
quickly at first boot to bypass graphics mode!&lt;/p&gt;&lt;h3&gt;Graphics modes&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;videoinfo&lt;/code&gt; command might be your friend in this case,
it will list supported modes and you can go back down to a fallback resolution
with the following incantation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;chroma language-sh display&quot;&gt;set gfxmode=&amp;quot;1024x768x32,auto&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which was a fancy resolution in the early years.  ;-)
Now that I think of it,
staying in the monochrome console probably makes more sense in that case.
But,
if you&amp;#39;ve read this far then you&amp;#39;ve learned how to handle other situations,
like if the text is too big, or way too small on your 8k!&lt;/p&gt;&lt;h2&gt;Tested&lt;/h2&gt;&lt;p&gt;This has been tested installing from:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Fedora 44&lt;/li&gt;
&lt;li&gt;Arch 26.07&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So far.
Doesn&amp;#39;t use many fancy features so should run in older versions,
but we&amp;#39;ll see.&lt;/p&gt;&lt;p&gt;With these images,
that have loaded successfully:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;.iso files&lt;/li&gt;
&lt;li&gt;.efi files&lt;/li&gt;
&lt;li&gt;memtest86 binaries that use the linux boot protocol.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Recommended Images&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://archlinux.org/&quot;&gt;Arch&lt;/a&gt;        - Up to date desktop, rolling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fedoraproject.org/&quot;&gt;Fedora&lt;/a&gt;  - Up to date desktop, every 6-month release&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linuxmint.com/&quot;&gt;Mint&lt;/a&gt;    - Long-term support (LTS) desktop, 2-year release&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://tails.net/&quot;&gt;Tails&lt;/a&gt;           - Anonymity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.kali.org/&quot;&gt;Kali&lt;/a&gt;         - Forensics, pentesting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://memtest.org/&quot;&gt;Memtest86&lt;/a&gt;     - RAM tester&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pbatard/UEFI-Shell/releases&quot;&gt;UEFI Shell&lt;/a&gt; -
The shellx64.efi works.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pbatard/UEFI-Shell/releases&quot;&gt;Mosby&lt;/a&gt; -
looked interesting.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;For memtest you can download the &amp;quot;Binary Files&amp;quot; link,
unpack the archive and copy the &lt;code&gt;*_x86_64&lt;/code&gt; file to the &lt;code&gt;/os-images&lt;/code&gt; folder on
the data partition of the removable drive.&lt;/p&gt;&lt;h2&gt;Inspiration and Thanks&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/grub/manual/grub/html_node/index.html&quot;&gt;https://www.gnu.org/software/grub/manual/grub/html_node/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/title/Multiboot_USB_drive&quot;&gt;https://wiki.archlinux.org/title/Multiboot_USB_drive&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Also cribbed a number of grub scripting techniques from these similar projects:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aguslr/multibootusb&quot;&gt;https://github.com/aguslr/multibootusb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hackerncoder/multibootusb&quot;&gt;https://github.com/hackerncoder/multibootusb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/thias/glim&quot;&gt;https://github.com/thias/glim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Not to mention looking at the grub.cfg of the many ISO images themselves.&lt;/p&gt;&lt;h2&gt;Dev Guide&lt;/h2&gt;&lt;h3&gt;Contributing Support Files&lt;/h3&gt;&lt;p&gt;Need support for your favorite distro?
Please make a merge request with your &lt;code&gt;menuentry&lt;/code&gt; stanza in a name.cfg file
under the support folder.
The script filename must match the prefix of the boot image filename,
up until the first dash or period &lt;code&gt;-.&lt;/code&gt;,
with a &lt;code&gt;.cfg&lt;/code&gt; extension at the end.&lt;/p&gt;&lt;p&gt;I suggest getting started by looking in the last two repos linked above for
example boot commands and arguments for your product of choice.
Also,
mount your .iso file of interest as a loopback drive or open with an archiver.
Looking around the folders will give quite a bit of information,
such as paths to the kernel etc.&lt;/p&gt;&lt;p&gt;Then refactor the script using the guidelines below.&lt;/p&gt;&lt;details&gt;&lt;summary&gt; &lt;b&gt;Repo Tour&lt;/b&gt; &lt;/summary&gt;
&lt;p&gt;In addition to the two main scripts mentioned already,
additional descriptions follow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Root folder - besides setup and update,
it also includes these Bash support scripts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;setup-drive.sh&lt;/code&gt; - carves up the flash drive, destroyer of worlds.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;update-tbk.sh&lt;/code&gt; - updates the settings and menus of GRUB,
optionally GRUB itself and/or its fonts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;generate-cfg.sh&lt;/code&gt; - builds the &lt;code&gt;grub/options.cfg&lt;/code&gt; using a template.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_config.sh&lt;/code&gt; - numerous customization variables are here&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_error_checks.sh&lt;/code&gt; - looks for issues before allowing &lt;code&gt;setup-&lt;/code&gt; and
&lt;code&gt;update-&lt;/code&gt; to proceed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_lib.sh&lt;/code&gt; - clean up and output routines.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;docs&lt;/code&gt; -
contains several text files, explaining various topics.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;grub&lt;/code&gt; -
the folder where the main .cfg files are located.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;grub.cfg&lt;/code&gt; - main entry point.
Loads the rest, some at startup, others on demand.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;lib.cfg&lt;/code&gt; - library functions, init graphics, calendar, sort, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;options.cfg&lt;/code&gt; - file to hold settings received from Bash.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;search.cfg&lt;/code&gt; - the main loop that looks for files under os-images&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;utils.cfg&lt;/code&gt; - where the utility submenu entries are&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;help.cfg&lt;/code&gt; - where the help entries are&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;grub/support&lt;/code&gt; -
Where we place .cfg files that either directly apply to an .iso file,
or if they apply to a group they can be named with an underscore at the front.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;grub/examples&lt;/code&gt;
Experiments from before we learned about loopback.cfg,
good coding examples of grub-script.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;&lt;details&gt;&lt;summary&gt; &lt;b&gt;Guidelines&lt;/b&gt; &lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use defensive scripting (test -f, etc),
though keep in mind we&amp;#39;ve already validated the existence of the image file,
or we wouldn&amp;#39;t have made it to your script.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use existing files for style guidelines,
Remove redundant code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A comment on what obscure boot parameters do and when they are required is
helpful.
Since you&amp;#39;re validating the entry,
it is a good time to experiment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use plenty of whitespace—we&amp;#39;re not running out on the these short files.
Four space indents, and single blank lines between significant,
dense, or commands of differing functionality.&lt;/p&gt;
&lt;p&gt;Long boot options are probably better indented on their own lines,
using a backslash to continue the line is supported in grub script.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a number of complicated parameter combos are recognized,
you may want to create a submenu for several entries to be chosen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use a unicode character in front of the entry title as an icon.&lt;/p&gt;
&lt;p&gt;Currently using ◎ for recognized isos,
⟳ for loopback.cfg support,
⌁ for executable binaries like .efi,
and ⏵ for sub-menus.
Ⓔ is given for yet unrecognized files that need to use the &amp;quot;e&amp;quot; key for the
script to be written to successfully boot.&lt;/p&gt;
&lt;p&gt;If there is a cool looking character that matches even better that&amp;#39;s fine as
well,
however note that the font is currently limited to points &amp;lt;= 0xFFFF,
and does not support everything under that,
which eliminates most Asian writing systems, emojis, and more.  #TODO&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the mkloop function (search.cfg) to make your loop device.
When used, and you 1) return from an image menu,
or 2) there is an error and you are thrown back to the main menu,
the next choice will avoid the &amp;quot;device already exists!&amp;quot; error.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;&lt;details&gt;&lt;summary&gt; &lt;b&gt;Variables&lt;/b&gt; &lt;/summary&gt;
&lt;p&gt;In your script,
you&amp;#39;ll have the following variables at your disposal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$P1&lt;/code&gt; - Grub-style path to the first partition of the removable drive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$P2&lt;/code&gt; - Grub-style path to the second partition of the removable drive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$root&lt;/code&gt; - Grub-style path to the ESP of the removable drive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$prefix&lt;/code&gt; - the folder typically at/called &lt;code&gt;$root/grub2&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$full_path&lt;/code&gt; - Full grub-style path to the current image file,
including (drive,) notation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$path&lt;/code&gt; - Unix-style /absolute/path to the file, without (drive,) notation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$filename&lt;/code&gt; - The whole filename, without path.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$basename&lt;/code&gt; - The alpha-numeric front of the filename,
up to the first dash or period &lt;code&gt;-.&lt;/code&gt;.
Would call it a prefix, but that name is taken.  :-/&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;&lt;h2&gt;Standard?&lt;/h2&gt;&lt;p&gt;Wouldn&amp;#39;t it be great if there were a standard for booting these things and we
did not have to make a custom loader script for almost every one?&lt;/p&gt;&lt;p&gt;If anyone knows anything about that or would like to start one,
let&amp;#39;s hear it.
Oh—well:&lt;/p&gt;&lt;h3&gt;Loopback.cfg&lt;/h3&gt;&lt;p&gt;Looking thru the eye-sos,
we found several references to a &lt;code&gt;loopback.cfg&lt;/code&gt; and finally an URL.
That wiki seems to be down,
but did dig the page up from the wayback:
&lt;a href=&quot;https://web.archive.org/web/20240108122718/https://www.supergrubdisk.org/wiki/Loopback.cfg&quot;&gt;loopback.cfg&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;The loopback.cfg file must be found at the path /boot/grub/loopback.cfg.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;That is the case,
except for Blue Hat distros which use grub2.  :-/
Ok, found a way around that.
Support could be better.&lt;/p&gt;&lt;h2&gt;Trustworthy Technology&lt;/h2&gt;&lt;p&gt;That&amp;#39;s all folks!
Learn more about this project,
and what inspired it,
at
&lt;a href=&quot;https://trustworthy.technology/&quot;&gt;trustworthy.technology&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Kollect: The Native KDE Link Collector I Built for Myself</title>
<link>https://blog.hofstede.it/kollect-the-native-kde-link-collector-i-built-for-myself/</link>
<guid isPermaLink="false">M7tRQYccvi9UfK6162vrbYd8hAqGf98FznqC1A==</guid>
<pubDate>Tue, 14 Jul 2026 22:08:58 +0000</pubDate>
<description>Kollect is a small native Plasma 6 application I wrote to get interesting links out of browser tabs and into a durable collection. It uses Kirigami and C++ on the desktop, plain TOML files by default, optional multi-user server storage, OpenRouter-powered metadata, KWallet for secrets, and a proper Fedora RPM. The source is not public, but the design is worth documenting.</description>
<content:encoded>&lt;hr/&gt;&lt;p&gt;&lt;img src=&quot;https://blog.hofstede.it/images/2026-07-14-kollect-kde-link-collector.webp&quot; alt=&quot;Kollect on KDE Plasma, showing links grouped into ISO week 2026w29 and the metadata detail view for a collected article&quot; title=&quot;Kollect is deliberately a desktop application: weekly link groups on the left, the selected article and its metadata on the right, and no browser pretending to be a window manager.&quot;/&gt;&lt;/p&gt;&lt;p&gt;I have a very predictable failure mode when reading the web. I open an interesting article, decide I will come back to it later, and leave the tab open. Then I do the same thing another twenty times. The tabs stop being a reading list and become archaeological layers.&lt;/p&gt;&lt;p&gt;Browser bookmarks never fixed this for me. They are good at preserving a &lt;span&gt;URL&lt;/span&gt;, but a &lt;span&gt;URL&lt;/span&gt; and a title are not enough to answer the question I actually have two weeks later: &lt;em&gt;why did I save this?&lt;/em&gt; Read-it-later services answer more of that question, but most of them turn a small personal collection into another account, another cloud database, and often another web application.&lt;/p&gt;&lt;p&gt;So I built &lt;strong&gt;Kollect&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Kollect is a small native &lt;span&gt;KDE&lt;/span&gt; Plasma 6 link collector. I paste a &lt;span&gt;URL&lt;/span&gt;, and it immediately files the link into the current &lt;span&gt;ISO&lt;/span&gt; week. In the background it fetches the page and asks an OpenRouter model to extract a useful title, publication date, author, tags, a primary topic, and a short summary. The result is a collection I can skim later instead of a graveyard of titles I no longer recognise.&lt;/p&gt;&lt;p&gt;This is not a product announcement. I have not published the application or its source, and there is no download link hiding at the end of this article. It is a personal 0.1 application built around my own workflow. But the design came together cleanly enough that it is worth documenting, especially because it combines several things I care about: a genuinely native Linux desktop, boring local files, optional self-hosting, secrets in KWallet, and distribution-native packaging.&lt;/p&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Table of Contents&lt;/li&gt;&lt;li&gt;What using it looks like&lt;/li&gt;&lt;li&gt;A native Plasma application, on purpose&lt;/li&gt;&lt;li&gt;Local-first means ordinary files&lt;/li&gt;&lt;li&gt;Enrichment without turning the app into a chatbot&lt;/li&gt;&lt;li&gt;Secrets belong in KWallet&lt;/li&gt;&lt;li&gt;One interface, two storage backends&lt;/li&gt;&lt;li&gt;The optional server&lt;/li&gt;&lt;li&gt;Packaged as a Fedora application, not a build directory&lt;/li&gt;&lt;li&gt;Things I deliberately did not build&lt;/li&gt;&lt;li&gt;The part I like most&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h2&gt;What using it looks like&lt;/h2&gt;&lt;p&gt;The main interaction is intentionally uneventful. Paste or type a link into the field and press Enter. That is it.&lt;/p&gt;&lt;p&gt;There are a few other paths because the best capture tool is the one that does not interrupt what I am doing:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;Ctrl+Shift+V&lt;/code&gt; adds whatever &lt;span&gt;URL&lt;/span&gt; is currently on the clipboard.&lt;/li&gt;&lt;li&gt;A &lt;span&gt;URL&lt;/span&gt; can be dragged and dropped anywhere onto the window.&lt;/li&gt;&lt;li&gt;&lt;code&gt;kollect https://example.net/article&lt;/code&gt; adds a &lt;span&gt;URL&lt;/span&gt; passed on the command line.&lt;/li&gt;&lt;li&gt;The desktop file registers Kollect as an &lt;span&gt;HTTP&lt;/span&gt; and &lt;span&gt;HTTPS&lt;/span&gt;&lt;span&gt;URL&lt;/span&gt; handler, so it can receive links from other desktop applications.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The entry appears immediately with a pending indicator. Metadata fetching is asynchronous, so a slow website or &lt;span&gt;API&lt;/span&gt; call does not freeze the interface. When enrichment completes, the raw &lt;span&gt;URL&lt;/span&gt; turns into a recognisable headline with a topic and tags. If fetching fails, the entry remains in the collection, changes to an error state, and can be retried from the context menu.&lt;/p&gt;&lt;p&gt;Links are grouped into folders such as &lt;code&gt;2026w29&lt;/code&gt;. The current week is expanded by default, older weeks are collapsed, and both weeks and entries are sorted newest first. Clicking an entry opens the detail page shown in the screenshot: the original &lt;span&gt;URL&lt;/span&gt;, author, publication date, topic, tags, collection time, and summary. From there I can open the page, copy its &lt;span&gt;URL&lt;/span&gt;, re-fetch metadata, or delete the entry.&lt;/p&gt;&lt;p&gt;That last part matters. Kollect does not try to become a browser. It remembers and organises links, then hands them back to the browser when I actually want to read them.&lt;/p&gt;&lt;h2&gt;A native Plasma application, on purpose&lt;/h2&gt;&lt;p&gt;Kollect is not an Electron application, a local web server with a tray icon, or a Python &lt;span&gt;GUI&lt;/span&gt; wearing a vaguely native stylesheet. The desktop client is C++20 with Qt 6, &lt;span&gt;KDE&lt;/span&gt; Frameworks 6, &lt;span&gt;QML&lt;/span&gt;, and Kirigami.&lt;/p&gt;&lt;p&gt;The executable owns the application logic and exposes one &lt;code&gt;KollectApp&lt;/code&gt; object to &lt;span&gt;QML&lt;/span&gt;. The interface is split into three small &lt;span&gt;QML&lt;/span&gt; files:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;Main.qml&lt;/code&gt; contains the application window, global drawer, capture field, weekly list, drag-and-drop area, and delete confirmation.&lt;/li&gt;&lt;li&gt;&lt;code&gt;DetailPage.qml&lt;/code&gt; renders one selected entry and its actions.&lt;/li&gt;&lt;li&gt;&lt;code&gt;SettingsDialog.qml&lt;/code&gt; configures OpenRouter and the optional sync server.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Kirigami provides the application structure, actions, responsive pages, form layout, inline messages, passive notifications, spacing, and icon integration. Qt Quick Controls uses &lt;code&gt;org.kde.desktop&lt;/code&gt;, so widgets follow the active Plasma style rather than drawing a separate visual universe inside the window. The application uses the system icon theme and standard &lt;span&gt;KDE&lt;/span&gt; shortcuts such as the Preferences, Close, and Quit keys.&lt;/p&gt;&lt;p&gt;This buys more than appearance. The global drawer behaves like a &lt;span&gt;KDE&lt;/span&gt; global drawer. Actions can move between the toolbar and overflow areas as space changes. Labels are selectable where that is useful. Notifications use the expected Plasma presentation. The result feels at home on my desktop because it is built out of the same primitives as the rest of the desktop.&lt;/p&gt;&lt;p&gt;The C++ side follows the usual Qt model/view boundary. &lt;code&gt;LinkModel&lt;/code&gt; is a &lt;code&gt;QAbstractListModel&lt;/code&gt; which presents both week headers and entries to the &lt;span&gt;QML&lt;/span&gt;&lt;code&gt;ListView&lt;/code&gt;. Roles expose the title, &lt;span&gt;URL&lt;/span&gt;, topic, tags, timestamp, state, and summary. A store emits &lt;code&gt;entryAdded&lt;/code&gt;, &lt;code&gt;entryUpdated&lt;/code&gt;, &lt;code&gt;entryRemoved&lt;/code&gt;, or &lt;code&gt;reloaded&lt;/code&gt;, the model rebuilds or updates the relevant row, and &lt;span&gt;QML&lt;/span&gt; reacts. The view does not need to know whether that store is a directory on disk or an &lt;span&gt;HTTP&lt;/span&gt;&lt;span&gt;API&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;That separation became the key to the entire design.&lt;/p&gt;&lt;h2&gt;Local-first means ordinary files&lt;/h2&gt;&lt;p&gt;The default backend is &lt;code&gt;LocalLinkStore&lt;/code&gt;, and it stores the collection here:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;~/.local/share/kollect/
├── 2026w28/
│   └── example-org-an-interesting-article.toml
└── 2026w29/
    ├── vermaden-wordpress-com-gitlab-on-freebsd.toml
    └── lwn-net-articles.toml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is one directory per &lt;span&gt;ISO&lt;/span&gt; week and one &lt;span&gt;TOML&lt;/span&gt; document per link. A real entry looks roughly like this:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;url=&amp;quot;https://vermaden.wordpress.com/2026/07/09/gitlab-on-freebsd/&amp;quot;added_at=&amp;quot;2026-07-14T16:38:21&amp;quot;status=&amp;quot;done&amp;quot;headline=&amp;quot;GitLab on FreeBSD&amp;quot;date=&amp;quot;2026-07-09&amp;quot;tags=[&amp;quot;freebsd&amp;quot;,&amp;quot;gitlab&amp;quot;,&amp;quot;server&amp;quot;,&amp;quot;git&amp;quot;,&amp;quot;postgresql&amp;quot;,&amp;quot;nginx&amp;quot;]topic=&amp;quot;FreeBSD&amp;quot;author=&amp;quot;vermaden&amp;quot;summary=&amp;quot;A step-by-step guide to installing and configuring a self-hosted GitLab server on FreeBSD. The setup uses a dedicated bhyve VM and a PostgreSQL, Redis, Nginx, and GitLab-CE backend stack.&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is deliberately not a single opaque database. I can inspect the files with &lt;code&gt;less&lt;/code&gt;, search them with &lt;code&gt;rg&lt;/code&gt;, copy one entry, synchronise the directory with any file tool, put it in a private Git repository, or write a conversion script ten years from now without first reconstructing an abandoned application’s database schema.&lt;/p&gt;&lt;p&gt;The file name is derived from the host and the last meaningful &lt;span&gt;URL&lt;/span&gt; path segment, normalised to a lowercase slug and capped at 80 characters. If two links in a week produce the same slug, Kollect adds &lt;code&gt;-2&lt;/code&gt;, &lt;code&gt;-3&lt;/code&gt;, and so on. Duplicate URLs are rejected across the whole collection before a file is created.&lt;/p&gt;&lt;p&gt;Writes go through &lt;code&gt;QSaveFile&lt;/code&gt;. That gives the local backend an important property for almost no complexity: a new document is written and committed atomically instead of truncating the existing file in place. A crash during a metadata update should not leave half a &lt;span&gt;TOML&lt;/span&gt; document behind. Deleting the final entry in a week also removes the now-empty week directory.&lt;/p&gt;&lt;p&gt;The state machine is tiny and visible in the data:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;pending  -&amp;gt;  done
   |
   +----&amp;gt; error  -&amp;gt;  pending (manual re-fetch)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;span&gt;URL&lt;/span&gt; is persisted in &lt;code&gt;pending&lt;/code&gt; state before any network request begins. Metadata is helpful, but it is not allowed to decide whether the link itself survives.&lt;/p&gt;&lt;h2&gt;Enrichment without turning the app into a chatbot&lt;/h2&gt;&lt;p&gt;The &lt;span&gt;AI&lt;/span&gt; part of Kollect is intentionally narrow. There is no chat panel and no prompt box. A model is used as a structured metadata extractor because web pages are inconsistent and because a useful two-to-four sentence reminder is hard to derive from &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags alone.&lt;/p&gt;&lt;p&gt;For each queued entry, Kollect performs two network operations:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;It fetches the page with Qt’s network stack, follows redirects only when they do not downgrade security (Qt’s NoLessSafeRedirectPolicy), and reads at most 2 MiB. A 30-second timeout covers both this request and the OpenRouter call that follows.&lt;/li&gt;&lt;li&gt;It removes scripts, styles, &lt;span&gt;SVG&lt;/span&gt;, templates, comments, and &lt;span&gt;HTML&lt;/span&gt; markup, decodes entities with &lt;code&gt;QTextDocument&lt;/code&gt;, normalises whitespace, and keeps at most 14,000 characters of readable text.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;That text and the &lt;span&gt;URL&lt;/span&gt; go to OpenRouter’s chat-completions endpoint. The request demands one &lt;span&gt;JSON&lt;/span&gt; object with exactly the fields Kollect understands: &lt;code&gt;headline&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;, &lt;code&gt;topic&lt;/code&gt;, &lt;code&gt;author&lt;/code&gt;, and &lt;code&gt;summary&lt;/code&gt;. In production I use the Chinese &lt;a href=&quot;https://openrouter.ai/minimax/minimax-m3&quot;&gt;MiniMax M3&lt;/a&gt; model under the OpenRouter identifier &lt;code&gt;minimax/minimax-m3&lt;/code&gt;. It is more than capable enough for website summaries and, as of July 14, 2026, costs $0.30 per million input tokens and $1.20 per million output tokens. The model is a normal setting and can be replaced without rebuilding the application. Kollect also requests &lt;span&gt;JSON&lt;/span&gt; response formatting and defensively extracts the outermost &lt;code&gt;{ ... }&lt;/code&gt; span because models occasionally wrap &lt;span&gt;JSON&lt;/span&gt; in a Markdown fence despite being told not to.&lt;/p&gt;&lt;p&gt;Jobs run through a simple in-process queue, one at a time. That avoids a burst of page downloads and &lt;span&gt;API&lt;/span&gt; calls when I paste several links in quick succession. It also makes error handling predictable: finish or fail one entry, then schedule the next job on the Qt event loop.&lt;/p&gt;&lt;p&gt;There is an obvious privacy boundary here which should not be hand-waved away. &lt;strong&gt;Local storage does not mean offline processing.&lt;/strong&gt; Enrichment sends the link and extracted page text to OpenRouter and whichever model provider handles the selected model. Anyone using this design should make that decision consciously and should not feed it private pages or sensitive intranet URLs. Without an &lt;span&gt;API&lt;/span&gt; key, the link is still collected, but enrichment ends in an error state.&lt;/p&gt;&lt;h2&gt;Secrets belong in KWallet&lt;/h2&gt;&lt;p&gt;Kollect needs two credentials: the OpenRouter &lt;span&gt;API&lt;/span&gt; key and, when server mode is enabled, a bearer token. On Plasma, both belong in KWallet.&lt;/p&gt;&lt;p&gt;The client talks directly to &lt;code&gt;org.kde.kwalletd6&lt;/code&gt; over D-Bus, opens the user’s network wallet asynchronously since that call may display an unlock dialog, and stores passwords under a dedicated &lt;code&gt;Kollect&lt;/code&gt; folder. Loading is additionally deferred until the Qt event loop is running, so no secret can be reported before the rest of the application has connected to the corresponding signals. Metadata jobs and remote requests wait until the corresponding secret has been resolved instead of racing application startup.&lt;/p&gt;&lt;p&gt;Non-secret settings live in &lt;code&gt;~/.config/kollectrc&lt;/code&gt; through KConfig: model name, server &lt;span&gt;URL&lt;/span&gt;, username, and whether the remote backend is enabled. An older &lt;span&gt;API&lt;/span&gt; key found in that config is migrated into KWallet the first time a wallet becomes available and then removed from the config file.&lt;/p&gt;&lt;p&gt;There are pragmatic fallbacks. If KWallet is unavailable, secrets can be stored in the config file, and the OpenRouter key can come from &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;. That is useful in unusual sessions and during development, but KWallet is the intended path on a normal Plasma desktop.&lt;/p&gt;&lt;h2&gt;One interface, two storage backends&lt;/h2&gt;&lt;p&gt;I originally needed Kollect on one machine, so local &lt;span&gt;TOML&lt;/span&gt; was the right starting point. Then came the predictable next requirement: the same collection on more than one workstation.&lt;/p&gt;&lt;p&gt;I did not want to destroy the local design by making the server mandatory. Instead, &lt;code&gt;LinkStore&lt;/code&gt; defines the operations the rest of the application needs, while two implementations provide persistence:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;QML  &amp;lt;-&amp;gt;  LinkModel  &amp;lt;-&amp;gt;  KollectApp
                \             /
                 \           /
                  LinkStore
                 /         \
        LocalLinkStore   RemoteLinkStore
           TOML files       JSON/HTTP&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At startup, &lt;code&gt;KollectApp&lt;/code&gt; reads the configuration and constructs exactly one backend. Everything above it stays the same. Adding an entry, updating metadata, deleting it, detecting duplicates, sorting weeks, and feeding the view all use the shared abstraction.&lt;/p&gt;&lt;p&gt;The remote backend is deliberately small. Once a token is available, it loads the user’s complete collection with &lt;code&gt;GET /entries&lt;/code&gt;. An entry update is a full-document &lt;code&gt;PUT&lt;/code&gt; to &lt;code&gt;/entries/{week}/{entry_id}&lt;/code&gt;, and deletion uses the corresponding &lt;code&gt;DELETE&lt;/code&gt;. The &lt;span&gt;JSON&lt;/span&gt; representation carries the same fields as the &lt;span&gt;TOML&lt;/span&gt; representation, so switching storage does not change what an entry means.&lt;/p&gt;&lt;p&gt;Server mode also has a one-time &lt;strong&gt;Upload Local Collection&lt;/strong&gt; action. It reads the existing &lt;span&gt;TOML&lt;/span&gt; backend, skips URLs or IDs already present remotely, and pushes the rest. Local files are left untouched.&lt;/p&gt;&lt;p&gt;It is important to call this what it is: &lt;strong&gt;an alternative remote store, not bidirectional offline synchronisation&lt;/strong&gt;. In server mode the server is the source of truth and the client needs a network connection. There is no conflict-resolution algorithm, offline write journal, or background merge between &lt;span&gt;TOML&lt;/span&gt; and SQLite. Building those features would be possible, but they would turn a clean storage switch into a distributed-systems project. For my use, an honest online backend is the better tradeoff.&lt;/p&gt;&lt;h2&gt;The optional server&lt;/h2&gt;&lt;p&gt;The server is a separate, compact Python application built with FastAPI, SQLAlchemy 2, Pydantic, and SQLite. Its complete public surface is five operations:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Path&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;code&gt;POST&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/auth/login&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Exchange a username and password for a bearer token&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/entries&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Return the authenticated user’s collection&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PUT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/entries/{week}/{entry_id}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Create or replace a complete entry&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/entries/{week}/{entry_id}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Delete one entry&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/healthz&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Liveness check without authentication&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;User passwords are hashed with Argon2. Login creates a random 32-byte &lt;span&gt;URL&lt;/span&gt;-safe token, returns it once, and stores only its &lt;span&gt;SHA&lt;/span&gt;-256 hash in the database. A leaked SQLite file therefore does not directly reveal reusable bearer tokens. Every entry is keyed by user, week, and entry &lt;span&gt;ID&lt;/span&gt;, and a uniqueness constraint prevents the same user from collecting one &lt;span&gt;URL&lt;/span&gt; under multiple IDs. Different users are isolated and may independently save the same &lt;span&gt;URL&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;Administration is intentionally &lt;span&gt;CLI&lt;/span&gt;-only. The server package provides commands to create users, change passwords, and list accounts. I do not need an admin web interface for a private service with a handful of users, and not building one means there is no admin web interface to secure.&lt;/p&gt;&lt;p&gt;The &lt;span&gt;API&lt;/span&gt; tests cover the parts that would hurt if they broke: failed login, missing and invalid tokens, the full &lt;span&gt;CRUD&lt;/span&gt; round trip, duplicate &lt;span&gt;URL&lt;/span&gt; conflicts, and isolation between two users.&lt;/p&gt;&lt;p&gt;Deployment is equally unsurprising. A small &lt;code&gt;python:3.12-slim&lt;/code&gt; image installs the server package, runs as &lt;span&gt;UID&lt;/span&gt; 1000, and keeps SQLite under &lt;code&gt;/data&lt;/code&gt;. A rootless Podman Quadlet binds it to &lt;code&gt;127.0.0.1:8000&lt;/code&gt;, stores data in a named volume, restarts on failure, and can start with the user’s systemd session. If I expose it beyond localhost, it goes behind a &lt;span&gt;TLS&lt;/span&gt;-terminating reverse proxy because the bearer token is an &lt;span&gt;HTTP&lt;/span&gt; header, not magic.&lt;/p&gt;&lt;h2&gt;Packaged as a Fedora application, not a build directory&lt;/h2&gt;&lt;p&gt;I run Fedora on my Plasma desktops, so Kollect is packaged as an &lt;span&gt;RPM&lt;/span&gt;. This sounds like a finishing detail, but it changes how an application feels in daily use. A program launched out of &lt;code&gt;~/src/project/build/&lt;/code&gt; is still a project. A program installed through &lt;span&gt;RPM&lt;/span&gt;, visible in the application launcher, tracked by the package database, and removable cleanly is part of the system.&lt;/p&gt;&lt;p&gt;The package uses Fedora’s CMake macros and declares the actual build stack:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;CMake, &lt;span&gt;GCC&lt;/span&gt; C++, and Extra CMake Modules&lt;/li&gt;&lt;li&gt;Qt 6 base and declarative development packages&lt;/li&gt;&lt;li&gt;&lt;span&gt;KDE&lt;/span&gt; Frameworks 6 KConfig, KCoreAddons, and KI18n development packages&lt;/li&gt;&lt;li&gt;Kirigami and &lt;code&gt;qqc2-desktop-style&lt;/code&gt; as explicit &lt;span&gt;QML&lt;/span&gt; runtime requirements&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That last point is easy to miss. &lt;span&gt;RPM&lt;/span&gt; dependency generation sees linked &lt;span&gt;ELF&lt;/span&gt; libraries rather well, but &lt;span&gt;QML&lt;/span&gt; imports loaded at runtime are not always inferred. Declaring Kirigami and the desktop Qt Quick style explicitly prevents the classic result where the package installs successfully and the application immediately fails because a &lt;span&gt;QML&lt;/span&gt; module is absent.&lt;/p&gt;&lt;p&gt;The &lt;span&gt;RPM&lt;/span&gt; installs the &lt;code&gt;kollect&lt;/code&gt; executable and &lt;code&gt;org.kde.kollect.desktop&lt;/code&gt;, then validates the desktop file during &lt;code&gt;%check&lt;/code&gt;. The build helper derives the version from the spec, creates a clean source archive from the current Git &lt;code&gt;HEAD&lt;/code&gt;, and hands that tarball to &lt;code&gt;rpmbuild&lt;/code&gt;. The package is therefore reproducible from committed source rather than whatever untracked experiment happens to be lying in the worktree.&lt;/p&gt;&lt;p&gt;For development, the underlying build remains conventional:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;cmake-Bbuild-DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake--buildbuild-j&amp;quot;$(nproc)&amp;quot;
./build/kollect&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For daily use, I install the &lt;span&gt;RPM&lt;/span&gt;. &lt;span&gt;KDE&lt;/span&gt; gets a proper desktop entry, &lt;code&gt;%u&lt;/code&gt;&lt;span&gt;URL&lt;/span&gt; handling, the standard bookmarks icon from the current icon theme, and a binary under the normal system prefix.&lt;/p&gt;&lt;h2&gt;Things I deliberately did not build&lt;/h2&gt;&lt;p&gt;Small applications stay pleasant when they are allowed to have boundaries. Kollect 0.1 does not have browser extensions, full-text article archiving, reading progress, a mobile client, collaborative lists, server-side metadata workers, or magical offline conflict resolution.&lt;/p&gt;&lt;p&gt;It also does not currently extract metadata locally. The model call is useful, but it introduces cost, network dependence, and the privacy boundary described above. A future local model or deterministic extractor could fit behind the existing &lt;code&gt;MetadataFetcher&lt;/code&gt; interface, but I would only add it when it improves the actual workflow rather than the feature list.&lt;/p&gt;&lt;p&gt;The server is optional because a server should remain optional for a link collector. The &lt;span&gt;TOML&lt;/span&gt; backend is not a demo mode that exists until a user signs up. It is the simplest complete version of the application and the one with the best long-term ownership story. Remote storage solves a real multi-machine problem, but it is allowed to remain an add-on.&lt;/p&gt;&lt;h2&gt;The part I like most&lt;/h2&gt;&lt;p&gt;Kollect is not technically enormous. That is exactly why I like it.&lt;/p&gt;&lt;p&gt;It takes one recurring irritation, too many tabs and too little context, and gives it a narrow desktop-shaped solution. The interface is native to Plasma. The default data format is readable without Kollect. Writes are atomic. Secrets use the desktop wallet. The &lt;span&gt;AI&lt;/span&gt; model has one constrained job. The remote service can be self-hosted, but the application does not require it. Fedora gets a real package rather than a &lt;code&gt;curl | bash&lt;/code&gt; installer.&lt;/p&gt;&lt;p&gt;Most importantly, I know where the data is and what every moving part does. If I stop maintaining the client tomorrow, the local collection remains a directory of &lt;span&gt;TOML&lt;/span&gt; files. If I stop running the server, SQLite remains a documented database full of ordinary rows. There is no export button I need to trust and no service whose business model has to survive longer than my bookmarks.&lt;/p&gt;&lt;p&gt;That is the kind of personal software I want more of: small, native, inspectable, and built to solve the problem in front of me without trying to own everything around it.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Big Blue thinks small, again, with POWER tower</title>
<link>https://www.theregister.com/systems/2026/07/14/big-blue-thinks-small-again-with-power-tower/5270851</link>
<enclosure type="image/jpeg" length="0" url="https://image.theregister.com/1682856.jpg?imageId=1682856&amp;x=0&amp;y=0&amp;cropw=100&amp;croph=100&amp;panox=0&amp;panoy=0&amp;panow=100&amp;panoh=100&amp;width=1200&amp;height=683"></enclosure>
<guid isPermaLink="false">vdH9tcdqTlnxHFGchNYMt0LYWcmn8ClC04zuqg==</guid>
<pubDate>Tue, 14 Jul 2026 18:05:25 +0000</pubDate>
<description>The last proprietary minicomputer, now in ‘deskside’ form if you fancy that</description>
<content:encoded>&lt;p&gt;IBM has again teased small hardware, this time in the form of an update for its smallest POWER server.&lt;/p&gt;&lt;p&gt;The model S1112, teased Tuesday in a &lt;a href=&quot;https://www.ibm.com/docs/en/announcements/power-s1112-server&quot;&gt;customer &lt;/a&gt;&lt;a href=&quot;https://www.ibm.com/docs/en/announcements/power-s1112-server&quot;&gt;announcement&lt;/a&gt;, is a 2U, single-socket POWER11 server IBM offers in rack-mountable and what the company calls “Tower/deskside configuration.”&lt;/p&gt;&lt;p&gt;The rackable model can handle a ten-core POWER processor. The Tower/deskside form factor machine must make do with a four-core engine&lt;/p&gt;&lt;div&gt;

        &lt;span&gt;REG AD&lt;/span&gt;
        
        
&lt;/div&gt;&lt;p&gt;IBM seems to have two roles in mind for the new machines: edge deployments and standalone use by those who are taking their first strides into using the last remaining proprietary minicomputer ecosystem.&lt;/p&gt;&lt;div&gt;

        &lt;span&gt;REG AD&lt;/span&gt;
        
        
&lt;/div&gt;&lt;p&gt;One is edge deployments. The other is as an entry-level box, with the description of the tower unit suggesting its very existence means “even the smallest customers” can use it as an on-ramp to more POWER implementations.&lt;/p&gt;&lt;p&gt;News of the S1112 marks the second time in a week that IBM has gone low with modest hardware. Last week Big Blue &lt;a href=&quot;https://www.theregister.com/systems/2026/07/07/ibm-teases-new-rackable-mainframes-that-complete-the-z17-family/5267423&quot;&gt;teased the &lt;/a&gt;&lt;a href=&quot;https://www.theregister.com/systems/2026/07/07/ibm-teases-new-rackable-mainframes-that-complete-the-z17-family/5267423&quot;&gt;z&lt;/a&gt;&lt;a href=&quot;https://www.theregister.com/systems/2026/07/07/ibm-teases-new-rackable-mainframes-that-complete-the-z17-family/5267423&quot;&gt;17 ME2&lt;/a&gt;, a rackable mainframe that it said completed its range by offering a smaller and cheaper piece of hardware.&lt;/p&gt;&lt;div&gt;
    
    &lt;div&gt;
        &lt;h2&gt;MORE CONTEXT&lt;/h2&gt;
        &lt;ul&gt;&lt;li&gt;
    &lt;a href=&quot;https://www.theregister.com/os-platforms/2026/07/10/red-hat-offers-rhel-support-forever-for-those-who-need-to-lock-in-to-legacy-tech/5269640&quot;&gt;
        
            &lt;h3&gt;Red Hat offers RHEL support ‘forever’ for those who need to lock in to legacy tech&lt;/h3&gt;
    &lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&quot;https://www.theregister.com/systems/2026/07/07/ibm-teases-new-rackable-mainframes-that-complete-the-z17-family/5267423&quot;&gt;
        
            &lt;h3&gt;IBM teases new rackable mainframes that ‘complete’ the z17 family&lt;/h3&gt;
    &lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&quot;https://www.theregister.com/os-platforms/2026/07/06/zombie-who-owns-unix-lawsuit-comes-alive-again/5266761&quot;&gt;
        
            &lt;h3&gt;Zombie ‘who owns Unix?’ lawsuit comes alive again&lt;/h3&gt;
    &lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&quot;https://www.theregister.com/systems/2026/06/25/ibm-stacks-up-a-sub-nanometer-chip-future/5261555&quot;&gt;
        
            &lt;h3&gt;IBM stacks up a sub-nanometer chip future&lt;/h3&gt;
    &lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
    &lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The twin launches continue IBM’s policy of creating smaller versions of its enterprise hardware, albeit well after launch of big iron: the first POWER 11 boxes landed in July 2025 and the first z17 series mainframes debuted in April of the same year.&lt;/p&gt;&lt;p&gt;The S1112 includes a quartet of DIMM slots and can handle up to 512GB of DDR5 memory. The box runs IBM i, AIX, and Linux – or all three because it supports IBM’s PowerVM virtualization tools.&lt;/p&gt;&lt;p&gt;In an almost certain non-coincidence, Big Blue on Tuesday also &lt;a href=&quot;https://www.ibm.com/docs/en/announcements/power-virtualization-platform-enhancements-3q-2026&quot;&gt;announced&lt;/a&gt; upgrades for PowerVM including improved automation and support for the S1112.&lt;/p&gt;&lt;p&gt;Big Blue has also looked after users of bigger POWER fleets, by expanding the number of Spyre accelerators – IBM’s neural processing units – that POWER servers can support from eight to twelve. IBM pitches POWER as a capable AI platform, so allowing it to use more accelerators can’t hurt.&lt;/p&gt;&lt;p&gt;IBM plans to start selling most of the kit described above on July 24, although customers who crave the S1112 to deploy in Taiwan will have to wait until September. 15. Would-be buyers in South Africa, India, and China must wait longer still, until December 11. ®&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Meetily: Privacy-First AI Meeting Assistant for Windows, macOS &amp; Linux</title>
<link>https://firethering.com/meetily-privacy-first-ai-meeting-assistant/</link>
<guid isPermaLink="false">CzA3D7_rWxVjWucLZ_E40QMzZ33bAqreQ9RI-w==</guid>
<pubDate>Tue, 14 Jul 2026 16:24:25 +0000</pubDate>
<description>Meetily is a free and open-source AI meeting assistant that records, transcribes, and summarizes meetings completely on your own device. Its not like other cloud-based meeting assistants, It keeps your conversations private by processing everything locally while supporting multiple AI providers for intelligent meeting summaries.</description>
<content:encoded>Meetily is a free and open-source AI meeting assistant that records, transcribes, and summarizes meetings completely on your own device. Its not like other cloud-based meeting assistants, It keeps your conversations private by processing everything locally while supporting multiple AI providers for intelligent meeting summaries.</content:encoded>
</item>
<item>
<title>OmniRoute: Connect All AI Models &amp; Providers Through One API</title>
<link>https://firethering.com/omniroute-connect-ai-models-providers-one-api/</link>
<guid isPermaLink="false">dStgCjYppKkGZZvkWd2CYF4ROSat5cCHxs8pCw==</guid>
<pubDate>Tue, 14 Jul 2026 16:24:25 +0000</pubDate>
<description>OmniRoute makes it easy to connect your favorite AI tools to hundreds of AI providers through a single endpoint. With automatic provider switching, smart routing, token optimization, and support for popular coding assistants, it helps you build AI applications without worrying about rate limits or changing APIs.</description>
<content:encoded>OmniRoute makes it easy to connect your favorite AI tools to hundreds of AI providers through a single endpoint. With automatic provider switching, smart routing, token optimization, and support for popular coding assistants, it helps you build AI applications without worrying about rate limits or changing APIs.</content:encoded>
</item>
<item>
<title>A highly available WireGuard VPN setup</title>
<link>https://0l.de/blog/2022/07/wireguard-ha/</link>
<guid isPermaLink="false">eT4I41wGM54egokIaA2fRKAHflQ92W8K6vekRg==</guid>
<pubDate>Tue, 14 Jul 2026 14:10:51 +0000</pubDate>
<description>WireGuard is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs), and was designed with the goals of ease of use, high speed performance, and low attack surface.</description>
<content:encoded>&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/Logo_of_WireGuard.DAM1CYIc_1GeaYm.svg&quot; alt=&quot;WireGuard Logo&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://wireguard.com/&quot;&gt;WireGuard&lt;/a&gt; is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs), and was designed with the goals of ease of use, high speed performance, and low attack surface.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;My Journey to WireGuard&lt;/h2&gt;&lt;/div&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/tinclogo.DaT4EzD__Z2iddrR.webp&quot; alt=&quot;Tinc Logo&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Tinc Logo.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I’ve been using it in my home lab setup since about 2020.
When, in the end of 2021, it was finally merged into the Linux mainline with release 5.9, I started to replace my former &lt;a href=&quot;https://tinc-vpn.org/&quot;&gt;Tinc-VPN&lt;/a&gt; setup with it.
Tinc-VPN is another great open source VPN solution.
Unfortunately, its development has stalled over the last years which motivated me to look for alternatives.
In contrast to WireGuard, Tinc runs as a user-space daemon and uses tun / tap devices which adds a significant processing overhead.
Like WireGuard, it is also using UDP for tunneling data, but falls back to TCP in situations where direct datagram connectivity is not feasible.
Another big advantage of Tinc is its ability to form a mesh of nodes and to route traffic within it when direct P2P connections are not possible due to firewall restrictions.
At the same time, this mesh is also used for facilitating direct connections by signaling endpoint addresses of &lt;a href=&quot;https://nl.wikipedia.org/wiki/Network_address_translation&quot;&gt;NATed&lt;/a&gt; hosts.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/tinc_mesh.BtkhiVQG_ZbYpXH.webp&quot; alt=&quot;Tinc&amp;#39;s mesh capability&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Tinc&amp;#39;s mesh capability.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This mesh functionality made Tinc quite robust against the failure of single nodes as usually we could route traffic via other paths.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Highly Available WireGuard server setup&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;To counteract this shortcoming, this blog post will present a highly available WireGuard setup using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_Router_Redundancy_Protocol&quot;&gt;Virtual Router Redundancy Protocol (VRRP)&lt;/a&gt; as implemented by the &lt;a href=&quot;https://keepalived.readthedocs.io/&quot;&gt;keepalived&lt;/a&gt; daemon.&lt;/p&gt;&lt;p&gt;That said, it is worth noting that this setup does will not bring back some of the beloved features of Tinc.
Both meshing, the peer and and endpoint discovery features of Tinc are currently and will never be supported by WireGuard.
Jason A. Donenfeld the author of WireGuard focused the design of WireGuard on simplicity, performance and auditability.
Hence advanced features like the ones mentioned will only be available to WireGuard by additional agents / daemons which control and configure WireGuard for you.
Examples for such are &lt;a href=&quot;https://tailscale.com/&quot;&gt;Tailscale&lt;/a&gt;, &lt;a href=&quot;https://www.netmaker.io/&quot;&gt;Netmaker&lt;/a&gt; and &lt;a href=&quot;https://netbird.io/&quot;&gt;Netbird&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The setup presented in this post is a so called active / standby configuration consisting of two almost equal configured Linux servers running both WireGuard and the keepalived daemon.
As the name suggest only one of those two servers will by actively handling WireGuard tunneling traffic while the other one stands by for the event of a failure or maintenance of the active node.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/wg_vrrip.BeFA9NiG_Z28SaSs.svg&quot; alt=&quot;VRRP Wireguard Setup&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;VRRP Wireguard Setup.&lt;/figcaption&gt;&lt;/figure&gt;&lt;div&gt;&lt;h3&gt;Requirements&lt;/h3&gt;&lt;/div&gt;&lt;p&gt;Before get started some requirements for the setup:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;2 Servers running Linux 5.9 or newer.&lt;/li&gt;&lt;li&gt;A working Wireguard configuration.&lt;/li&gt;&lt;li&gt;A local L2 network segment two which both servers are connected.&lt;/li&gt;&lt;li&gt;Upstream connectivity without NATing via gateway connected to the network segment (usually provided by your internet or hosting provider).&lt;/li&gt;&lt;li&gt;An unused address to be used as &lt;em&gt;Virtual IP&lt;/em&gt; (VIP) which roamed between the two servers by VRRP.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;An important point is here the assumption that we are running both servers in the same &lt;em&gt;switched&lt;/em&gt; network segment as this is a requirement for VRRP.
We are also assuming that the upstream gateway performs no NATing.
This guide covers only IPv6 addressing.
However all steps can be also adapted or repeated for a dual stack or IPv4-only setup.&lt;/p&gt;&lt;div&gt;&lt;h3&gt;Detailed steps&lt;/h3&gt;&lt;/div&gt;&lt;p&gt;Here are some of the specifics for my setup which need to be adapted by you:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Server Key&lt;/strong&gt; (same use by both servers)
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Private&lt;/strong&gt;: &lt;code&gt;YIEDx+A2ONo5+uv3mrk/p7ileL3T5QQ8hleQK0IYEEI=&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Public:&lt;/strong&gt;&lt;code&gt;XGubrkGtuECdvoykKeUiNMigk2onfLCPfEo9Im+vmx8=&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Peer Key&lt;/strong&gt; (In this example we only have a single peer)
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Private:&lt;/strong&gt;&lt;code&gt;OIbpWVIVVBOtWfwkmXkFRN7Q/jBdfYtsGt7j97aHx1Q=&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Public:&lt;/strong&gt;&lt;code&gt;3NGl6gTOGs6ai0RE91VmVFgF+N4gw1EBG11KOeiKJAg=&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Public Server Subnet:&lt;/strong&gt; 2001:DB8:1::/64
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Gateway:&lt;/strong&gt; 2001:DB8:1::1&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Virtual IP:&lt;/strong&gt; 2001:DB8:1::2&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Server A:&lt;/strong&gt; 2001:DB8:1:::3&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Server B:&lt;/strong&gt; 2001:DB8:1::4&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;WireGuard Tunnel Subnet:&lt;/strong&gt; 2001:DB8:2::1/64
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Server:&lt;/strong&gt; 2001:DB8:2::1 (same used by both servers)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Peer:&lt;/strong&gt; 2001:DB8:2::2&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Interface names&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Wireguard:&lt;/strong&gt; wg1&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Upstream:&lt;/strong&gt; eno1&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Prepare servers&lt;/p&gt;&lt;p&gt;We start of preparing the two servers by installing WireGuard and keepalived:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;sudoaptinstallkeepalivedwireguard-toolsiproute2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Next we configure a WireGuard interface on both servers using exactly the &lt;strong&gt;same&lt;/strong&gt; configuration file at &lt;code&gt;/etc/wireguard/wg1.conf&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;[Interface]

Address= 2001:DB8:2::1/64

PrivateKey= YIEDx+A2ONo5+uv3mrk/p7ileL3T5QQ8hleQK0IYEEI=

ListenPort= 51800



[Peer]

PublicKey= 3NGl6gTOGs6ai0RE91VmVFgF+N4gw1EBG11KOeiKJAg=

AllowedIPs= 2001:DB8:2::2/128

PersistentKeepalive= 25&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Similarly, a reciprocal configuration file is needed on the client side which skip here for brevity.
Before proceeding, we activate the interface on &lt;strong&gt;both&lt;/strong&gt; servers:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;systemctlenable--nowwg-quick@wg1



wgshowwg1# Check if interface is up&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configuring Keepalived&lt;/p&gt;&lt;p&gt;Create a configuration file for keepalived at &lt;code&gt;/etc/keepalived/keepalived.conf&lt;/code&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;global_defs {

enable_script_security

script_user root

}



# Check if the server the WireGuard interface configured

vrrp_script check_wg {

script &amp;quot;/usr/bin/wg show wg1&amp;quot;

user root

}



vrrp_instance wg_v6 {

interface eno1

virtual_router_id 52

notify /usr/local/bin/keepalived-wg.sh



state BACKUP # use BACKUP for Server B

priority 99 # use 100 for Server B



virtual_ipaddress {

2001:DB8:1::1/64

}



track_script {

check_wg

}

}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Create a notification script for keepalived at &lt;code&gt;/usr/local/bin/keepalived-wg.sh&lt;/code&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;#!/usr/bin/env bash



TYPE=$1

NAME=$2

STATE=$3

PRIO=$4



WGIF=wg1



case${STATE}in

MASTER)

iplinksetupdev${WGIF}

;;



BACKUP|FAULT|STOP|DELETED)

iplinksetdowndev${WGIF}

;;



*)

echo&amp;quot;unknown state&amp;quot;

exit1

esac&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Now start the keepalived daemon:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;chmod+x/usr/local/bin/keepalived-wg.sh

systemctlenable--nowkeepalived&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Testing the fail over&lt;/p&gt;&lt;p&gt;In our configuration, Server A has a higher VRRP priority and as such will be preferred if both servers are healthy.
To test our setup, we simply bring down the WireGuard interface on Server A and observe how the VIP gets moved to Server B.
From the WireGuard peers perspective not much changes.
In fact no connections will be dropped during the fail-over.
Internally, the clients WireGuard interface renegotiate the handshake.
However, that step is actually not observable by the user.&lt;/p&gt;&lt;p&gt;Run the following commands on Server A while alongside test the connectivity from the client side through the tunnel via &lt;code&gt;ping -i0.2 2001:DB8:2::1&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;# Check that keepalived has moved the VIP to interface eno1

ipaddrshowdeveno1



# Bring down the Wireguard interface

wg-quickdownwg1



# Keepalived should now have moved the VIP to Server B

ipaddrshowdeveno1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;h2&gt;Going further&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;In my personal network, I operate a &lt;a href=&quot;https://en.wikipedia.org/wiki/Interior_gateway_protocol&quot;&gt;Interior Gateway Protocol (IGP)&lt;/a&gt; to dynamically route traffic within and also towards other networks.
Common IGPs are OSPF, ISIS or BGP.
In my specific case, both Servers A &amp;amp; B run the Bird2 routing daemon with interior and exterior BGP sessions.&lt;/p&gt;&lt;p&gt;So how does the WireGuard HA setup interoperates with my interior routing? Quite well actually.
As my notify script (&lt;code&gt;keepalive-wg.sh&lt;/code&gt;) will automatically bring up / down the interface, the routes attached to the interface will be picked up by &lt;a href=&quot;https://bird.network.cz/?get_doc&amp;amp;v=20&amp;amp;f=bird-6.html#ss6.5&quot;&gt;Bird’s direct protocol&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I am also planning to extend my WireGuard agent cunīcu (&lt;a href=&quot;https://codeberg.org/cunicu/cunicu&quot;&gt;&lt;span&gt;/cunicu/cunicu&lt;/span&gt;&lt;/a&gt; ) to support the synchronization of WireGuard interface configurations between multiple servers.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Background&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;Surprisingly, the setup works by using Keepalived and does not require any iptables or nftables magic to rewrite source IP addresses.
I’ve seen some people mentioning that SNAT / DNAT would be required to convince WireGuard to use the virtual IP instead of the server addresses.
However, in my experience this was not necessary.&lt;/p&gt;&lt;p&gt;Another concern has been that the backup Wireguard interface still might attempt to establish a handshake with its peers.
This would quite certainly interfere with the handshakes originated by the current master server.
However, also this has not been proven to be the case.
I assume the fact that our notify script brings down the WireGuard interface on the backup server causes them to cease all communication with its peers.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Gaining Root Access on Netgear Nighthawk Mobile 5G/LTE Routers</title>
<link>https://0l.de/blog/2022/06/netgear-m5-root-access/</link>
<guid isPermaLink="false">XDo7gH_TDq0B__uEUVxnhJSdcxfsINugOXimxA==</guid>
<pubDate>Tue, 14 Jul 2026 14:10:51 +0000</pubDate>
<description>This blog posts covers the required steps to gain root access via Telnet on Netgear Nighthawk Mobile 5G/LTE Routers. Its the first post in a small series covering my experiences playing around with this device.</description>
<content:encoded>&lt;p&gt;This blog posts covers the required steps to gain root access via Telnet on Netgear Nighthawk Mobile 5G/LTE Routers. Its the first post in a small series covering my experiences playing around with this device.&lt;/p&gt;&lt;p&gt;Last month I obtained one of Netgear’s latest mobile 5G routers, the &lt;a href=&quot;https://www.netgear.com/home/mobile-wifi/hotspots/mr5200/&quot;&gt;Netgear Nighthawk M5&lt;/a&gt; (model MR5200-100EUS) . Being one of the most expensive consumer 5G routers, I was lucky to get a fairly good second hand deal from eBay.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/Netgear-Nighthawk-M5-mobile-router-copy.Dt9FC3GW_Z2u6pLR.webp&quot; alt=&quot;Netgear Nighthawk M5 mobile 5G/LTE Router&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Netgear Nighthawk M5 mobile 5G/LTE Router.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The router is powered by &lt;a href=&quot;https://www.qualcomm.com/products/technology/modems/snapdragon-x55-5g-modem&quot;&gt;Qualcomm’s® Snapdragon™ X55 5G Modem-RF system&lt;/a&gt;. Looking closer at the internals of the device by checking the &lt;a href=&quot;https://fccid.io/PY319400469/&quot;&gt;FCC filing for the closely related American model MR5100&lt;/a&gt;, we can see that the system consists of a Qualcomm SDX55 chipset which combines both the mobile baseband and application processors.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Gaining Root Access&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;Gaining root access to the device is actually fairly simple in comparison to rooting modern Android-based devices. The router exposes an open TCP port providing an AT command interface. However, this port is only accessible via a tethered USB connection, &lt;strong&gt;not via Wifi&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Using this AT command interface, we can interact with the modem, unlock an extended command set which allows us enable a Telnet daemon.&lt;/p&gt;&lt;div&gt;&lt;h3&gt;Detailed Steps&lt;/h3&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Install the Sierra Wireless debug tools from bkerler (&lt;a href=&quot;https://github.com/bkerler/edl&quot;&gt;&lt;span&gt;/bkerler/edl&lt;/span&gt;&lt;/a&gt; )&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;sudoaptinstallpython3git

gitclonehttps://github.com/bkerler/edl.git

cdedl

sudopythonsetup.pyinstall&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;(More detailed installation instructions are covered in the README file of the repo.)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Connect your machine via USB-C to the Netgear router&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Make sure to disconnect from the Netgear Wifi&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Open a terminal an connect to the AT command interface via netcat (nc)&lt;/p&gt;&lt;p&gt;(Make sure not to miss the -c option as it will the enable nc to use the proper CRLF line-endings which are required for the AT interface).&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;nc-c192.168.1.15510&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Once connected to the AT command interface, you need to request a unlock challenge code by sending&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;AT!OPENLOCK?&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The previous command will return a challenge code which we use to generate a corresponding response code via the previously installed &lt;code&gt;sierrakeygen.py&lt;/code&gt; tool:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;sierrakeygen.py-l&amp;lt;replace_with_challenge_code&amp;gt;-dSDX55&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The previous command will print out another &lt;code&gt;AT+OPENLOCK&lt;/code&gt; command which you need to copy verbatim back to your AT command session.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run the following AT commands to enable the Telnet daemon&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;AT!TELEN=1

AT!CUSTOM=&amp;quot;RDENABLE&amp;quot;, 1

AT!CUSTOM=&amp;quot;TELNETENABLE&amp;quot;, 1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;You can now close the AT command session by pressing Ctrl+C.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Power-cycle the Netgear Router to start the Telnet daemon&lt;/p&gt;&lt;p&gt;Voila, you can now telnet into the device via both the tethered USB-C cable or Wifi.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;nc-c172.23.156.12923

��������

mdm1623sdxprairie

/# uname -a

uname-a

Linuxsdxprairie4.14.117#1 PREEMPT Thu Aug 19 23:42:26 UTC 2021 armv7l GNU/Linux&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Please be aware that the device security is now breached as all devices connected to the Wifi or USB can gain root access to the device. The root Telnet login requires no password.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;h2&gt;Next steps&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;Before proceeding we should make sure that we can bring the device back to a secure state &lt;a href=&quot;https://0l.de/blog/2022/07/netgear-m5-ssh-access&quot;&gt;by replacing the Telnet by an Secure Shell (SSH) daemon&lt;/a&gt;. In one of the next posts of this series, I will be building a statically linked version of the Dropbear SSH server to replace Telnet.&lt;/p&gt;&lt;p&gt;Before continuing my reverse engineering efforts on the device, I would like to ensure that I will not brick the router while doing so &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-reveng&quot;&gt;by dumping the firmware and extract all the details from it&lt;/a&gt;. This will allow us to hopefully restore the device by flashing the original firmware. Maybe we will be able to run OpenWRT on it.&lt;/p&gt;&lt;p&gt;I have also designed &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-wall-mount&quot;&gt;a wall mount for the router&lt;/a&gt; which allows me to mount it permanently into by van.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Running a Xilinx hw_server as Docker Container</title>
<link>https://0l.de/blog/2022/02/dockerized-xilinx-hw-server/</link>
<guid isPermaLink="false">WtP6GpLqLDM26IGSO3FFA3QbqWnzTNKXd_oJjw==</guid>
<pubDate>Tue, 14 Jul 2026 14:10:51 +0000</pubDate>
<description>Dockerized Xilinx hw_server Setup.This article describes the necessary steps to run a Xilinx hw_server as a Docker container.</description>
<content:encoded>&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/setup.C7tu0nxW_1bnRrI.webp&quot; alt=&quot;Dockerized Xilinx hw_server Setup&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Dockerized Xilinx hw_server Setup.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This article describes the necessary steps to run a Xilinx &lt;code&gt;hw_server&lt;/code&gt; as a Docker container.&lt;/p&gt;&lt;p&gt;Xilinx’s &lt;code&gt;hw_server&lt;/code&gt; is a command line utility which handles JTAG communication between a Xilinx FPGA board and usually the Vivado IDE.
It can be used to configure the FPGA bitstream, connect to the embedded logic analyzer cores (ILA) or perform debugging of processor cores via &lt;a href=&quot;https://www.sourceware.org/gdb/&quot;&gt;GDB&lt;/a&gt; and the Xilinx System Debugger (XSDB).
The &lt;code&gt;hw_server&lt;/code&gt; is usually used when those tasks shall performed remotely as the connection between Vivado or XSDB is established via TCP connection and allows us to run it on a remote system.&lt;/p&gt;&lt;p&gt;Running the &lt;code&gt;hw_server&lt;/code&gt; as a Docker container has the benefit that its installation is simplified to starting a Docker container by running:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;dockerrun\

--restartunless-stopped\

--privileged\

--volume/dev/bus/usb:/dev/bus/usb\

--publish3121:3121\

--detach\

ghcr.io/stv0g/hw_server:v2021.2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;It also allows us to run the &lt;code&gt;hw_server&lt;/code&gt; on architectures which are not natively supported by Xilinx such as the commonly used Aarch / ARM64 and ARMv7 architectures found in Raspberry Pis.&lt;/p&gt;&lt;p&gt;This is enabled by Dockers support for running container images for non-native architectures.
I am using the &lt;code&gt;aptman/qus&lt;/code&gt; Docker image (&lt;a href=&quot;https://github.com/dbhi/qus&quot;&gt;&lt;span&gt;/dbhi/qus&lt;/span&gt;&lt;/a&gt; ) to setup this user-mode emulation.
The &lt;em&gt;qemu-user-static&lt;/em&gt; (&lt;strong&gt;qus&lt;/strong&gt;) image is a compilation of utilities, examples and references to build and execute OCI images (aka &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt; images) for foreign architectures using &lt;a href=&quot;https://www.qemu.org/&quot;&gt;QEMU&lt;/a&gt;’s &lt;a href=&quot;https://qemu-project.gitlab.io/qemu/user/index.html&quot;&gt;user-mode emulation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Run the following commands to run the &lt;code&gt;hw_server&lt;/code&gt; on a embedded device:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;# Install docker

sudoapt-getupdate&amp;amp;&amp;amp;sudoapt-getupgrade

curl-sSLhttps://get.docker.com|sh



# Start Docker

sudosystemctlenable--nowdocker



# Enable qemu-user emulation support for running amd64 Docker images

# *Note:* only required if your system arch is not amd64!

dockerrun--rm--privilegedaptman/qus-s---px86_64



# Run the hw_server

dockerrun--restartunless-stopped--privileged--volume/dev/bus/usb:/dev/bus/usb--publish3121:3121--detachghcr.io/stv0g/hw_server:v2021.2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;This setup has been tested with a Raspberry Pi 4 running the new 64-bit Debian Bullseye Raspberry Pi OS.&lt;/p&gt;&lt;p&gt;The pre-built Docker image for the &lt;code&gt;hw_server&lt;/code&gt; of Vivado 2021.2 is available via:&lt;/p&gt;&lt;center&gt;&lt;a href=&quot;https://codeberg.org/stv0g/xilinx-hw-server-docker/packages&quot;&gt;&lt;b&gt;/stv0g/xilinx-hw-server-docker (Packages)&lt;/b&gt;&lt;/a&gt;&lt;/center&gt;&lt;p&gt;Detailed instructions can be found at Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g/xilinx-hw-server-docker&quot;&gt;&lt;span&gt;/stv0g/xilinx-hw-server-docker&lt;/span&gt;&lt;/a&gt; .&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Encrypted credentials for Amazon AWS command line client</title>
<link>https://0l.de/blog/2015/09/awscli-credentials-tfa/</link>
<guid isPermaLink="false">90cIFPPaSefl_hYMxP1lddH4s3fckSdgnO7jTw==</guid>
<pubDate>Tue, 14 Jul 2026 14:10:51 +0000</pubDate>
<description>In this quick post I will show you how to use the password manager “password-store”1 to securely store your credentials used by the Amazon Webservices command line client.</description>
<content:encoded>&lt;p&gt;In this quick post I will show you how to use the password manager “&lt;a href=&quot;http://www.passwordstore.org&quot;&gt;password-store&lt;/a&gt;”&lt;sup&gt;1&lt;/sup&gt; to securely store your credentials used by the Amazon Webservices &lt;a href=&quot;https://aws.amazon.com/cli/&quot;&gt;command line client&lt;/a&gt;.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/aws_cli.C_euehf4_Zu6JGY.webp&quot; alt=&quot;AWS CLI Logo&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;AWS CLI Logo.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The installation for Mac and Linux system is fairly easy:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;pipinstallawscli&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The credentials are stored as key-value pairs inside a PGP-encrypted file.
Every time you call the AWS CLI tool, your keys will be decrypted and directly passed to the &lt;code&gt;aws&lt;/code&gt; tool.&lt;/p&gt;&lt;p&gt;Use &lt;code&gt;pass&lt;/code&gt; to add your keys in the store:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;passeditproviders/aws&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;An editor opens.
Use the following format:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;User: stv0g

Access-Key: AKB3ASJGBS3GOMXK6KPSQ

Secret-Key: vAAABn/PMAksd235gAs/FSshhr42dg2D4EY3&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Add the following snippet to your &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;functionaws{

localPASS=$(passproviders/aws)

localAWS=$(whichaws)



# Start original aws executable with short-lived keys

AWS_ACCESS_KEY_ID=$(sed-En&amp;#39;s/^Access-Key: (.*)/\1/p&amp;#39;&amp;lt;&amp;lt;&amp;lt;&amp;quot;$PASS&amp;quot;)\

AWS_SECRET_ACCESS_KEY=$(sed-En&amp;#39;s/^Secret-Key: (.*)/\1/p&amp;#39;&amp;lt;&amp;lt;&amp;lt;&amp;quot;$PASS&amp;quot;)$AWS$@

}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Then use the cli tool &lt;code&gt;aws&lt;/code&gt; as usual:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;awsiamlist-access-keys{&amp;quot;AccessKeyMetadata&amp;quot;: [ {&amp;quot;UserName&amp;quot;:&amp;quot;stv0g&amp;quot;,...`&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;section&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;I covered password-store already a few times earlier: &lt;a href=&quot;https://0l.de/blog/2015/06/ansible-credentials-tfa&quot;&gt;Use YubiKey and Password-store for Ansible credentials&lt;/a&gt;, &lt;a href=&quot;https://0l.de/blog/2015/06/hardware-security-token&quot;&gt;Workshop: Security Token&lt;/a&gt;. ↩&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;</content:encoded>
</item>
<item>
<title>Use Yubikey and Password-store for Ansible credentials</title>
<link>https://0l.de/blog/2015/06/ansible-credentials-tfa/</link>
<guid isPermaLink="false">Dl-y_pgLyHRXH3SvF7hvY8Adsv23vO5mY9SiwA==</guid>
<pubDate>Tue, 14 Jul 2026 14:10:51 +0000</pubDate>
<description>I spent some time over the last months to improve the security of servers and passwords.</description>
<content:encoded>&lt;p&gt;I spent some time over the last months to improve the security of servers and passwords.
In doing so, I started to orchestrate my servers using a configuration management tool called &lt;strong&gt;&lt;a href=&quot;https://www.ansible.com/home&quot;&gt;Ansible&lt;/a&gt;&lt;/strong&gt;.
This allows me to spin-up fresh servers in a few seconds and to get rid of year-old, polluted and insecure system images.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/ansible_loves_yubico.uOhjQpqw_Z1Lg7T3.webp&quot; alt=&quot;Ansible loves Yubico&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Ansible loves Yubico.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;My ‘single password for everything’ has been replaced by a new password policy which enforces individual passwords for every single service.
This was easier than I previously expected:&lt;/p&gt;&lt;p&gt;To unlock the ‘paranoid’ level, I additionally purchased a &lt;strong&gt;&lt;a href=&quot;https://www.yubico.com/products/yubikey-hardware/&quot;&gt;Yubikey&lt;/a&gt;&lt;/strong&gt; Neo token to handle the decryption of my login credentials in tamper-proof hardware.
‘&lt;strong&gt;&lt;a href=&quot;https://www.passwordstore.org/&quot;&gt;pass&lt;/a&gt;&lt;/strong&gt;’ is just a small shell script to glue several existing Unix tools together: Bash, pwgen, Git, xclip &amp;amp; GnuPG (obeying the Unix philosophy).
The passwords are stored in simple text files which are encrypted by PGP and stored in a directory structure which is managed in a Git repository.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/IMG_20150526_121142.BxqbqHBT_ZIFDyz.webp&quot; alt=&quot;Yubikey Neo und Neo-n&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;Yubikey Neo und Neo-n.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;There are already a tons of tutorials which present the tools I describes above.
I do not want to repeat all of it.
So, this post is dedicated to solve some smaller issues I encountered.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Use One-Time passwords across multiple servers&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;The Yubikey Neo can do much more than decrypting static passwords via GnuPG:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Generate passwords:
&lt;ul&gt;&lt;li&gt;fixed string (&lt;strong&gt;insecure!&lt;/strong&gt;)&lt;/li&gt;&lt;li&gt;with Yubico OTP algorithm&lt;/li&gt;&lt;li&gt;with OATH-HOTP algorithm&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Do challenge response authentication
&lt;ul&gt;&lt;li&gt;via FIDO’s U2F standard&lt;/li&gt;&lt;li&gt;with HMAC-SHA1 algorithm&lt;/li&gt;&lt;li&gt;with Yubico OTP algorithm&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Some third-party services already support FIDO U2F standard or traditional OATH-{H,T}OTP TFA, like used by the Google authenticator app.
I suggest to have a look at: &lt;a href=&quot;https://twofactorauth.org&quot;&gt;https://twofactorauth.org&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For private servers there are several PAM modules available to integrate OTP’s or Challenge Response (CR) methods.
Unfortunately, support for CR is not widespread across different SSH- and mail clients.&lt;/p&gt;&lt;p&gt;So, you want to use OTP’s which leds to another problem: OTP’s rely on a synchronized counter between the hardware token and the server.
Once you use multiple servers, those must be synchronized as well.
I’m using a central Radius server to facilitate this.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Integrate &lt;code&gt;pass&lt;/code&gt; into your Ansible workflow&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;Ansible uses SSH and Python scripts to manage several remote machines in parallel.
You must use key-based SSH authentication, because you do not want to type every password manually!
Additionally you need to get super user privileges for most of your administrative tasks on the remote machine.&lt;/p&gt;&lt;p&gt;The SSH authentication is handled by gpg-agents &lt;code&gt;--enable-ssh-support&lt;/code&gt; option and a PGP key on your token.&lt;/p&gt;&lt;p&gt;To get super user privileges, I use the following variable declaration my Ansible &lt;code&gt;group_vars/all&lt;/code&gt; file:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;pre&gt;&lt;code&gt;---

ansible_sudo_pass:&amp;quot;{{ lookup(&amp;#39;pipe&amp;#39;, &amp;#39;pass servers/&amp;#39; + inventory_hostname) }}&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;There is a separate root password for every server (e.g. &lt;code&gt;pass servers/lian.0l.de&lt;/code&gt;).
I wrote some Ansible roles to easily and periodically rotate these passwords.&lt;/p&gt;&lt;div&gt;&lt;h2&gt;Integrate ‘pass’ into OS X&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;There are already several plugins and extensions to integrate the &lt;code&gt;pass&lt;/code&gt; password store into other Programs like Firefox and Android.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/pass_osx_prompt.D9qNhijV_57ekQ.webp&quot; alt=&quot;A prompt for the password you want&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;A prompt for the password you want.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I added support for OS X by writing a small AppleScript which can be found here: &lt;a href=&quot;https://github.com/zx2c4/password-store/blob/master/contrib/pass.applescript&quot;&gt;&lt;span&gt;/zx2c4/password-store/contrib/pass.applescript&lt;/span&gt;&lt;/a&gt; .&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://0l.de/_astro/pass_osx_notification.Cyj1-no0_1gvijK.webp&quot; alt=&quot;A notification with countdown&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;A notification with countdown.&lt;/figcaption&gt;&lt;/figure&gt;</content:encoded>
</item>
<item>
<title>コマンドで重複行を排除して一度だけ表示する</title>
<link>https://www.bioerrorlog.work/entry/unique-lines-in-shell</link>
<enclosure type="image/jpeg" length="0" url="https://cdn.image.st-hatena.com/image/scale/3eb8368e41c1dd39fa52a7f0a0cd92b9833b2e2d/backend=imagemagick;version=1;width=1300/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2FB%2FBioErrorLog%2F20250417%2F20250417101021.png"></enclosure>
<guid isPermaLink="false">jGTWPRjhKlabgpSiMkomBZWJlz3gkJQuA8fNuw==</guid>
<pubDate>Mon, 13 Jul 2026 20:16:42 +0000</pubDate>
<description>awkで簡単にできます: awk &#39;!seen[$0]++&#39; はじめに コマンドで重複行を排除して一度だけ表示する コマンド解説 実行例 おわりに 参考 はじめに コマンドで重複行を排除して一度だけ表示する方法の備忘録を残します。 The English translation of this post is here. コマンドで重複行を排除して一度だけ表示する 下記コマンドで、重複行を排除して一度だけ表示可能です: awk &#39;!seen[$0]++&#39; コ...</description>
<content:encoded>&lt;p&gt;&lt;code&gt;awk&lt;/code&gt;で簡単にできます:&lt;/p&gt;&lt;pre&gt;awk &lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;!seen[$0]++&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;はじめに&lt;/li&gt;&lt;li&gt;コマンドで重複行を排除して一度だけ表示する&lt;ul&gt;&lt;li&gt;コマンド解説&lt;/li&gt;&lt;li&gt;実行例&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;おわりに&lt;/li&gt;&lt;li&gt;参考&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;はじめに&lt;/h2&gt;&lt;p&gt;コマンドで重複行を排除して一度だけ表示する方法の備忘録を残します。&lt;/p&gt;&lt;p&gt;&lt;em&gt;The English translation of this post is &lt;a href=&quot;https://en.bioerrorlog.work/entry/unique-lines-in-shell&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h2&gt;コマンドで重複行を排除して一度だけ表示する&lt;/h2&gt;&lt;p&gt;下記コマンドで、重複行を排除して一度だけ表示可能です:&lt;/p&gt;&lt;pre&gt;awk &lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;!seen[$0]++&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;h3&gt;コマンド解説&lt;/h3&gt;&lt;pre&gt;awk &lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;!seen[$0]++&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;$0&lt;/code&gt;: 現在処理している行全体&lt;/li&gt;&lt;li&gt;&lt;code&gt;seen[$0]&lt;/code&gt;: &amp;quot;現在処理している行全体&amp;quot;をキーとする連想配列&amp;quot;seen&amp;quot;の値&lt;/li&gt;&lt;li&gt;&lt;code&gt;seen[$0]++&lt;/code&gt;: &amp;quot;現在処理している行全体&amp;quot;をキーとする連想配列&amp;quot;seen&amp;quot;の値をインクリメント

&lt;ul&gt;&lt;li&gt;その行が初めて出てきた場合: 未定義 → 0&lt;/li&gt;&lt;li&gt;その行が既にカウントされている場合: 値が1増加&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;!seen[$0]++&lt;/code&gt;: NOT演算子付きでbool判定

&lt;ul&gt;&lt;li&gt;その行が初めて出てきた場合: &lt;code&gt;!0&lt;/code&gt; = true&lt;/li&gt;&lt;li&gt;その行が既にカウントされている場合: &lt;code&gt;!1(以上)&lt;/code&gt; = false&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;awk &amp;#39;!seen[$0]++&amp;#39;&lt;/code&gt;: その行が初めて出てきた場合のみtrueとなり表示&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;よって、このコマンドで重複行を排除して一度だけ表示することができます。&lt;/p&gt;&lt;h3&gt;実行例&lt;/h3&gt;&lt;p&gt;下記のようなファイル&lt;code&gt;list.txt&lt;/code&gt;の内容を、先ほどのコマンドで重複行を排除して表示してみます。&lt;/p&gt;&lt;pre&gt;apple
banana
apple
orange
banana
grape
apple&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;
実行コマンド:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;cat&lt;/span&gt; list.txt | awk &lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;!seen[$0]++&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;出力結果:&lt;/p&gt;&lt;pre&gt;apple
banana
orange
grape&lt;/pre&gt;&lt;p&gt;このように、重複行を排除して一度だけ表示されることが確認できました。&lt;/p&gt;&lt;h2&gt;おわりに&lt;/h2&gt;&lt;p&gt;以上、コマンドで重複行を排除して一度だけ表示する方法のメモでした。&lt;/p&gt;&lt;p&gt;どなたかの参考になれば幸いです。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://twitter.com/bioerrorlog?ref_src=twsrc%5Etfw&quot;&gt;Follow @bioerrorlog&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;[関連記事]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.bioerrorlog.work/entry/reading-shell-commands&quot;&gt;www.bioerrorlog.work&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;h2&gt;参考&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/gawk/manual/gawk.html&quot;&gt;The GNU Awk User’s Guide&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded>
</item>
<item>
<title>ZimaBoard2: The Full Review</title>
<link>https://gardinerbryant.com/zimaboard2-the-full-review/</link>
<enclosure type="image/jpeg" length="0" url="https://gardinerbryant.com/content/images/size/w1200/2026/07/PXL_20260706_231615582-1.jpg"></enclosure>
<guid isPermaLink="false">ZvxBBlwyDWCbsyJ2RsvvDh61FxtL4IuEY6WZog==</guid>
<pubDate>Mon, 13 Jul 2026 19:27:36 +0000</pubDate>
<description>The ZimaBoard 2 is a great, low power NAS for enthusiasts, DIYers, hobbyists, and folks looking to start dabbling with self-hosted at home. I&#39;ve been playing around with it for quite some time (thanks to IceWhale for sending it over to me to review) and I&#39;m happy</description>
<content:encoded>&lt;div&gt;
                        &lt;div&gt;
    &lt;div&gt;👍&lt;/div&gt;
    &lt;div&gt;
        &lt;p&gt;
            The product featured in this article was provided to the author free
            of charge for the purpose of review. That means:
        &lt;/p&gt;
        &lt;ul&gt;
            &lt;li&gt;Nobody was paid to write or publish this review.&lt;/li&gt;
            &lt;li&gt;The vendor did not get editorial input in, nor advanced screening
                of, this article.
            &lt;/li&gt;
            &lt;li&gt;
                This article may include affiliate links (which will have a 
                &lt;span&gt;tag&lt;/span&gt; icon).&lt;br/&gt;&lt;small&gt;We &lt;a href=&quot;https://heavyelement.com/ethics#2-caffiliate-links&quot;&gt;
                earn a modest commission&lt;/a&gt; off any purchase you make using 
                our links at no additional cost to you.&lt;/small&gt;
            &lt;/li&gt;
            &lt;li&gt;This article was written in accordance with our &lt;a href=&quot;https://heavyelement.com/ethics#2-bproduct-reviews&quot;&gt;Ethics Statement&lt;/a&gt;.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/div&gt;            &lt;/div&gt;&lt;p&gt;The ZimaBoard 2 is a great, low power NAS for enthusiasts, DIYers, hobbyists, and folks looking to start dabbling with self-hosted at home. I&amp;#39;ve been playing around with it for quite some time (thanks to IceWhale for sending it over to me to review) and I&amp;#39;m happy to note that it&amp;#39;s a &lt;em&gt;very&lt;/em&gt; fun device to play with!&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;What&amp;#39;s in the box?&lt;/h2&gt;&lt;h3&gt;Specifications&lt;/h3&gt;&lt;table&gt;
    &lt;tbody&gt;&lt;tr&gt;
        &lt;th&gt;CPU&lt;/th&gt; &lt;td&gt;x86 Intel N150&lt;br/&gt;&lt;small&gt;4 cores 4 threads 2.9GHz&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;RAM&lt;/th&gt;&lt;td&gt;DDR5 @ 6,400 MHz&lt;br/&gt;&lt;small&gt;8GB or 16GB&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;Storage&lt;/th&gt; &lt;td&gt;Dual native SATA&lt;br/&gt;&lt;small&gt;32GB or 64GB eMMC&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;Networking&lt;/th&gt; &lt;td&gt;Dual 2.5GbE&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Expansion&lt;/th&gt; &lt;td&gt;PCIe &amp;amp; USB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;I/O&lt;/th&gt; &lt;td&gt;USB 3.0 &amp;amp; Mini DisplayPort&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;Setup&lt;/th&gt; &lt;td&gt;ZimaOS GUI&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;Power&lt;/th&gt; &lt;td&gt;Fanless, ~6W idle&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;Cost&lt;/th&gt; &lt;td&gt;&lt;a href=&quot;https://metrics.gardinerbryant.com/q/zimaboard2-8gb?affiliate&quot;&gt;8GB RAM/32GB eMMC - $339&lt;/a&gt;&lt;br/&gt;&lt;a href=&quot;https://metrics.gardinerbryant.com/q/zimaboard2-16gb?affiliate&quot;&gt;16GB RAM/64GB eMMC- $399&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/specs-1-1.jpg&quot; alt=&quot;ZimaOS on the ZimaBoard2 Device info screen&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;&lt;span&gt;ZimaBoard2&amp;#39;s Device Info screen&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This particular model is the 8GB RAM/32GB eMMC variant which I feel is quite reasonably priced for what you get.&lt;/p&gt;&lt;p&gt;The Intel N150 is fitting for this class of NAS. With 4 cores and 6MB of cache, you&amp;#39;re not going to be doing extremely heavy stuff (like a local AI chat bot without a GPU/ASIC to assist) but it&amp;#39;s still more than enough to run a VM or install some of the built-in apps.&lt;/p&gt;&lt;h3&gt;This package&lt;/h3&gt;&lt;p&gt;In the box, the ZimaBoard2 came with the device, a little fan, a custom SATA/power breakout cable, two screwdrivers, a bunch of fasteners, a mini DisplayPort to HDMI adapter, and a DC power adapter. If I have one complaint about the form factor of this device, it&amp;#39;s that adapter. It&amp;#39;s pretty big and uses a barrel jack connection.&lt;/p&gt;&lt;p&gt;The box that this ships with can be upcycled into a stand for the ZimaBoard along with two 3.5&amp;quot; SATA drives. Neat touch!&lt;/p&gt;&lt;div&gt;&lt;div&gt;💢&lt;/div&gt;&lt;div&gt;The mini DisplayPort to HDMI adapter included in the box &lt;i&gt;&lt;em&gt;did not work&lt;/em&gt;&lt;/i&gt; for me no matter what I tried. I connected it to my ATEM Mini Extreme ISO, my daily driver LG monitors, my old Sony WEGA tube TV (yes, it has HDMI), and I even tried a portable monitor. It was simply e-waste.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;IceWhale shipped me the ZimaBoard2 along with an aluminum hard drive bay. The ZimaBoard fastens directly to it and can accommodate up to two 5 1/4&amp;quot; drives. This hard drive bay also comes with a PCIe riser.&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;Initial Setup&lt;/h2&gt;&lt;p&gt;The ZimaBoard 2 is easy to set up. The first thing you should do is remove the bottom of the chassis and find the fan header and connect the included fan to it.&lt;/p&gt;&lt;p&gt;Then remove the nearby screw located in the top of the chassis and fasten the fan to it.&lt;/p&gt;&lt;p&gt;Make sure that the fan&amp;#39;s wires won&amp;#39;t get pinched and replace the bottom of the enclosure. But don&amp;#39;t replace the screws just yet!&lt;/p&gt;&lt;p&gt;Find the longer fasteners that came with the HDD bay, align the holes in the bay to the chassis and then tighten the screws down one by one.&lt;/p&gt;&lt;p&gt;From there, you can populate the bay with up to two 5 1/4&amp;quot; drives and connect them via the included power/SATA cable.&lt;/p&gt;&lt;p&gt;Connect this to your network, (optionally) connect a monitor, and plug in the power...&lt;/p&gt;&lt;h3&gt;Software&lt;/h3&gt;&lt;p&gt;Now, you&amp;#39;ll want to go to a computer on the same network and start the software setup process.&lt;/p&gt;&lt;p&gt;Head into your browser and navigate to &lt;code&gt;casaos.local&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;If this doesn&amp;#39;t work, you&amp;#39;ll need to type in the IP address of your ZimaBoard into the address bar. To find this, you can connect a monitor to the DisplayPort and the readout will tell you. &lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/PXL_20260712_134812634-1-1.jpg&quot; alt=&quot;ZimaOS on the ZimaBoard2 display&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;&lt;span&gt;I apologize for the photo. I don&amp;#39;t have a great way of capturing DisplayPort video&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;div&gt;&lt;div&gt;💡&lt;/div&gt;&lt;div&gt;Alternatively, you can inspect your DHCP leases!&lt;/div&gt;&lt;/div&gt;&lt;p&gt;From here, you&amp;#39;ll want to follow the initial setup guide...&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/casaos1-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/casaos2-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/casaos3-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;Get started with the ZimaBoard 2&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;h3&gt;Update&lt;/h3&gt;&lt;p&gt;One mistake I made in &lt;a href=&quot;https://gardinerbryant.com/zima-board-2-unboxing-first-impressions/&quot;&gt;my first impressions video&lt;/a&gt; was that I didn&amp;#39;t upgrade the OS immediately.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-34.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-35.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;ZimaOS 1.6.2 Murjek update&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Well, actually, the OS didn&amp;#39;t &lt;em&gt;tell me&lt;/em&gt; that an update was available until the day after I filmed that video. I&amp;#39;m not sure why, but either way it meant some of the problems I had in the video were solved by a simple upgrade.&lt;/p&gt;&lt;p&gt;I recommend updating as soon as possible. The latest updates are terrific. This also means that the screenshots I&amp;#39;m using in the Disk Setup portion are on the older version of the OS.&lt;/p&gt;&lt;h3&gt;The Dashboard&lt;/h3&gt;&lt;p&gt;Like any NAS, the ZimaBoard2 has a GUI that&amp;#39;s accessible through your web browser.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-29.png&quot; alt=&quot;Dashboard for ZimaOS on the ZimaBoard2 &quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Built-in apps include the &lt;code&gt;App Store&lt;/code&gt;, &lt;code&gt;Files&lt;/code&gt;, &lt;code&gt;Backup&lt;/code&gt;, &lt;code&gt;ZVW&lt;/code&gt; (virtual machine manager), &lt;code&gt;PeerDrop&lt;/code&gt;, &lt;code&gt;Settings&lt;/code&gt;, and a link to the IceWhale Community.&lt;/p&gt;&lt;p&gt;Most of these are pretty self-explanatory, but before we get to any of that, we need to set up our hard drive.&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;Disk Setup&lt;/h2&gt;&lt;p&gt;When you connect a drive, you&amp;#39;ll see this prompt on the dashboard:&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk1-1.jpg&quot; alt=&quot;ZimaOS on the ZimaBoard2 dashboard - disk setup prompt&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Click the &amp;quot;Manage&amp;quot; button to start the setup process.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk2-1.jpg&quot; alt=&quot;ZimaOS on the ZimaBoard2 dashboard - Storage &amp;quot;Create Storage&amp;quot; prompt&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;&lt;span&gt;Click the &amp;quot;Start&amp;quot; button.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;On this screen, you can combine multiple drives to appear as a single disk. This is useful to increase throughput and aggregate capacity. Since I only have one drive, I just chose &amp;#39;Single use.&amp;#39;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk3-1.jpg&quot; alt=&quot;ZimaOS on the ZimaBoard2 dashboard - &amp;quot;Set up 1 new disks&amp;quot; screen&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Here, you can select &amp;quot;Need Format&amp;quot; to start the format process. You can also click the other button to see drive details. &lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk4-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk4.5-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;If your drive is already formatted with a support filesystem, you won&amp;#39;t need to format.&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Provide the format details including the name of this volume:&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk5-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk6-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;ZimaOS disk formatting configuration&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Once formatting is finished, click &amp;quot;Enable&amp;quot; to continue.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk7-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk8-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;ZimaOS disk configuration&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Now that we have a drive set up, we can start uploading files!&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk9-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/disk10-1.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;My glasses! I can&amp;#39;t see without my glasses!&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;hr/&gt;&lt;h2&gt;Use Cases&lt;/h2&gt;&lt;p&gt;If you&amp;#39;re considering picking one of these up, there are a few excellent use cases.&lt;/p&gt;&lt;h3&gt;#0 Built-in Functionality&lt;/h3&gt;&lt;p&gt;You can use the built in apps like &lt;code&gt;Files&lt;/code&gt;, &lt;code&gt;ZVM&lt;/code&gt;, and &lt;code&gt;Backup&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Files&lt;/strong&gt; allows you to manage your own files in a personal cloud. It also lets you share your files with other people!&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-31.png&quot; alt=&quot;ZimaOS on the ZimaBoard2 Files app&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Backup&lt;/strong&gt; helps you manage your backups across multiple devices.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-30.png&quot; alt=&quot;ZimaOS on the ZimaBoard2 Backup app&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;ZVM gives you a tidy GUI to manage virtual machines. Super handy for downloading vendor-created appliance-like ISOs for something like Home Assistant.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-32.png&quot; alt=&quot;ZimaOS on the ZimaBoard2 ZVM virtual machine manager&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;There&amp;#39;s also the App Store that will let you get other apps up and running quickly!&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-33.png&quot; alt=&quot;ZimaOS on the ZimaBoard2 App Store&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;h3&gt;#1 JellyFin (or other media server)&lt;/h3&gt;&lt;p&gt;If you didn&amp;#39;t know, &lt;a href=&quot;https://gardinerbryant.com/plexs-lifetime-pass-is-basically-dead-heres-how-to-switch-to-jellyfin/&quot;&gt;I&amp;#39;m a JellyFin fiend&lt;/a&gt;. It&amp;#39;s a fantastic, amazing, all-in-one self-hosted streaming app that gives you access to your media collection and stream from it like your own personal Netflix.&lt;/p&gt;&lt;p&gt;Setting up Jellyfin on the ZimaBoard is really straightforward.&lt;/p&gt;&lt;p&gt;Just head into the app store and Jellyfin should be towards the top. Select it and click Install:&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-36.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-37-1.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;Install Jellyfin from the ZimaOS App Store&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-38.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-39.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;Installation process for Jellyfin on the ZimaOS App Store&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Once it&amp;#39;s finished, you can then click the Jellyfin icon to launch your newly-installed application! &lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-40.png&quot; alt=&quot;Initial Jellyfin configuration screen running on ZimaOS on the ZimaBoard2 &quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;h3&gt;#2 Home Assistant&lt;/h3&gt;&lt;p&gt;Home Assistant in another terrific use case. If you&amp;#39;ve ever wanted to get into home automation, Home Assistant will be your jam.&lt;/p&gt;&lt;p&gt;Again, find Home Assistant in the App Store and mash that &amp;quot;Install&amp;quot; button. Once it&amp;#39;s done installing, click the icon!&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-41.png&quot; alt=&quot;Home Assistant icon on the ZimaOS dashboard on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-42.png&quot; alt=&quot;Initial configuration screen for Home Assistant on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;h3&gt;#3 qBittorrent&lt;/h3&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-43.png&quot; alt=&quot;qBittorrent icon on ZimaOS on the ZimaBoard2 &quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;If you are a benevolent person who loves Linux, you might be interested in seeding your favorite distro&amp;#39;s ISOs. And why wouldn&amp;#39;t you? It&amp;#39;s just a kind, loving thing to do.&lt;/p&gt;&lt;p&gt;But you may also not want to leave your desktop or laptop on all the time. That&amp;#39;s where qBittorent comes in.&lt;/p&gt;&lt;p&gt;Like the other apps here, click the icon to launch it. The first time you click it, you&amp;#39;ll see this screen:&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-46.png&quot; alt=&quot;qBittorrent Tips modal window on ZimaOS on the ZimaBoard2 &quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Before you log in, though, make sure you update the Download directory. This is done in the Settings modal and &lt;em&gt;not&lt;/em&gt; in qBittorrent. Click the edit icon on the above screen!&lt;/p&gt;&lt;p&gt;Scroll down to the &amp;quot;Volumes&amp;quot; section and click the folder icon for the second field &lt;code&gt;/DATA&lt;/code&gt;.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-51.png&quot; alt=&quot;qBittorrent settings on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Pick your &lt;code&gt;HDD-Storage&lt;/code&gt; and make a new folder:&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-53-1.png&quot; alt=&quot;qBittorrent app&amp;#39;s Volume settings on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Once you&amp;#39;ve done that, click &amp;quot;Save&amp;quot; in the Settings modal.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-54.png&quot; alt=&quot;Don&amp;#39;t forget to save qBittorrent&amp;#39;s settings on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;The username is &lt;code&gt;admin&lt;/code&gt;, but you&amp;#39;re going to need to find the password. Open the qBittorrent menu and select &amp;quot;Settings.&amp;quot; Then, in the top right corner, select the terminal icon. From here, choose the &amp;quot;Logs&amp;quot; file and you&amp;#39;ll see the password toward the end of the log file.&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-48.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-45-1.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-44-1.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;How to find your temporary password for qBittorrent&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Once you open qBittorrent, you&amp;#39;ll see the login screen.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-47.png&quot; alt=&quot;qBittorrent WebUI login screen on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-49.png&quot; alt=&quot;Downloading the Linux Mint 22.3 ISO using qBittorrent on ZimaOS on the ZimaBoard2&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Finally, click the gear icon and navigate to the WebUI tab. Set a Password and click Save.&lt;/p&gt;&lt;h3&gt;#5 PFSense Firewall&lt;/h3&gt;&lt;p&gt;The modem/router that your ISP provided you (probably) sucks. And &lt;em&gt;sucks really badly, at that&lt;/em&gt;. That&amp;#39;s why I set up &lt;a href=&quot;https://gardinerbryant.com/opnsense-nginx-reverse-proxy-for-your-homelab/&quot;&gt;my own firewall&lt;/a&gt; many moons ago. There are lots of reasons to create your own firewall that I won&amp;#39;t go into here. Suffice it to say: Wendell from Level1Techs told me it was the preferred option and who am I to disagree with Wendell?&lt;/p&gt;&lt;p&gt;PFSense is considered the premier DIYer&amp;#39;s firewall system and, to my surprise, &lt;a href=&quot;https://shop.zimaspace.com/blogs/zima-campaign-hub/install-pfsense-on-zimaboard-network-security&quot;&gt;Zima&amp;#39;s official docs have a pretty thorough guide for setting it up&lt;/a&gt;!&lt;/p&gt;&lt;div&gt;&lt;div&gt;👉&lt;/div&gt;&lt;div&gt; I haven&amp;#39;t personally tried setting up PFsense on the ZimaBoard 2.&lt;/div&gt;&lt;/div&gt;&lt;h2&gt;Final Thoughts&lt;/h2&gt;&lt;p&gt;The ZimaBoard2 is a terrific NAS for hobbyists, enthusiasts, and entry-level users.&lt;/p&gt;&lt;p&gt;The hardware is awesome. I love the form factor, the expandability with the PCIe port, and the dual 2.5Gbit NIC setup. It feels sturdy, industrial, and the optional hard drive bay is a welcome addition.&lt;/p&gt;&lt;p&gt;I have to say that the ZimaOS/CasaOS UI is &lt;em&gt;incredible&lt;/em&gt; and makes managing Docker containers absolutely painless. Plus, &lt;a href=&quot;https://github.com/IceWhaleTech/CasaOS/blob/main/LICENSE&quot;&gt;CasaOS is FOSS under the Apache license&lt;/a&gt;, and it&amp;#39;s written in Go! &lt;em&gt;Gotta love that.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Also of note: I&amp;#39;ve got Jellyfin, Home Assistant, and qBittorrent running and the system resources leaves room for even more applications in the future!&lt;/p&gt;&lt;figure&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-55.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;img src=&quot;https://gardinerbryant.com/content/images/2026/07/image-56.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;p&gt;&lt;span&gt;ZimaOS dashboard&amp;#39;s system resources readout while running Home Assistant, Jellyfin, and qBittorrent!&lt;/span&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I am very pleased with this device and it&amp;#39;s a welcome addition to my homelab!&lt;/p&gt;&lt;hr/&gt;&lt;div&gt;
            &lt;a href=&quot;https://www.google.com/preferences/source?q=gardinerbryant.com&quot;&gt;
            With Google recently announcing they&amp;#39;re &lt;em&gt;dismantling their search platform&lt;/em&gt;, there&amp;#39;s 
            no better time to add &lt;strong&gt;The Bryant Review&lt;/strong&gt; as one of your preferred sources.
            &lt;/a&gt;
        &lt;/div&gt;&lt;div&gt;
                    &lt;img src=&quot;https://gardinerbryant.com/content/images/size/w320/2026/03/avatar-1.jpg&quot; alt=&quot;Gardiner Bryant&quot; title=&quot;&quot;/&gt;
                &lt;h2&gt;About the Author:&lt;/h2&gt;
                &lt;h3&gt;
                    Gardiner Bryant
                &lt;/h3&gt;
                    &lt;p&gt;I&amp;#39;m an educator, free software advocate, and storyteller. My passion lies in Linux gaming, self-hosting, the fediverse, and the human stories behind the tech we use every day. I believe in privacy, justice, community, and integrity.&lt;/p&gt;
                &lt;footer&gt;
                    &lt;div&gt;
                            &lt;a href=&quot;https://heavyelement.com&quot;&gt;&lt;/a&gt;
                            &lt;a href=&quot;https://mastodon.online/@gardiner_bryant&quot;&gt;&lt;/a&gt;
                            &lt;a href=&quot;https://bsky.app/profile/heavyelement.com&quot;&gt;&lt;/a&gt;
                            &lt;a href=&quot;https://www.youtube.com/@gardiner_bryant&quot;&gt;&lt;/a&gt;
                        &lt;a href=&quot;https://gardinerbryant.com/author/gbryant/&quot;&gt;More from Gardiner Bryant&lt;/a&gt;
                    &lt;/div&gt;
                &lt;/footer&gt;
            &lt;/div&gt;</content:encoded>
</item>
<item>
<title>First look at the New GPU Cooler Prototype</title>
<link>https://esologic.com/new-cooler-first-look/</link>
<guid isPermaLink="false">fYbNVM_Ol1QSCH5bTuuD2k7bQiKSB3JSsKgDkw==</guid>
<pubDate>Mon, 13 Jul 2026 18:33:30 +0000</pubDate>
<description>For the past while I’ve been working on a major redesign of my high performance gpu cooler project. The rapid ascent of the LLM into the collective consciousness has sent the big players into a frenzy over datacenter GPUs. This is putting accelerating downward pressure on the price of all used compute GPUs, even the... The post First look at the New GPU Cooler Prototype appeared first on esologic.</description>
<content:encoded>&lt;p&gt;For the past while I’ve been working on a major redesign of my &lt;a href=&quot;https://esologic.com/cooler/&quot;&gt;high performance gpu cooler project&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The rapid ascent of the LLM into the collective consciousness has sent the big players into a frenzy over datacenter GPUs. This is putting accelerating downward pressure on the price of all used compute GPUs, even the historically pricey stuff. P100s can be had for ~$100, V100 16GB are selling for ~$500, any day now the lower VRAM Ampere cards are going to drop below $1000…&lt;/p&gt;&lt;p&gt;We need a new cooler that can support &lt;em&gt;any&lt;/em&gt; of these 300W GPUs, can be installed as densely as the cards, and is easy on the ears for homelab use. Pictured below are four prototype coolers installed on Tesla P100s:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-155431-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Four PCBs installed on Four P100s on the Open Bench Table build.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-154826-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail shot of the PCBs.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-154924-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Nested PCBs.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-155304-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Rightward looking coolers on the GPUs.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Like always, if you’re interesting in beta testing one of these coolers, send me a note. I’ve been keeping a list of people that have reached out since the original post and will likely be sending out a batch of coolers for feedback early next year.&lt;/p&gt;&lt;h2&gt;Endgame EOL’d GPU Box?&lt;/h2&gt;&lt;p&gt;Nominally out of date, the X99 Intel E5-* Xeon CPUs &lt;a href=&quot;https://forum.level1techs.com/t/x99-is-still-and-will-be-for-some-time-one-of-the-best-platforms-for-tech-enthusiast-and-home-servers/198164/4&quot;&gt;remain a favorite&lt;/a&gt; among homelabbers. CPUs are cheap, and the cores are plentiful. Relevant to the engineer interested in local LLM usage is the fact that that many of the workstation-class motherboards for these CPUs can mechanically support four x16 GPUs without breaking the bank.&lt;/p&gt;&lt;p&gt;In my mind, the Kepler, Maxwell and Pascal (to a lesser extent) series of NVidia compute GPUs sit in the same place. Irrelevant to volume businesses but potentially useful to small shops with specialized workloads.&lt;/p&gt;&lt;p&gt;In a way, I’ve been building up to a system like this &lt;a href=&quot;https://esologic.com/sliger-mods/#sliger-cx4200a-for-a-4x-tesla-p100-ollama-build&quot;&gt;for a while&lt;/a&gt; but &lt;strong&gt;having a suitable GPU cooler has remained the limiting factor&lt;/strong&gt;. There are also a bunch of &lt;a href=&quot;https://www.reddit.com/r/LocalLLaMA/comments/1f6hjwf/battle_of_the_cheap_gpus_lllama_31_8b_gguf_vs/?share_id=YcWde1NtsEDXiSemTDF33&amp;amp;utm_medium=ios_app&amp;amp;utm_name=ioscss&amp;amp;utm_source=share&amp;amp;utm_term=1&quot;&gt;amazing builds out there&lt;/a&gt; covering similar ground but I feel they probably ran into the same cooling-related problems I did. Now that the new cooler has matured to a working prototype, I can finally build this system and see how much performance we can squeeze out of these old parts.&lt;/p&gt;&lt;h2&gt;Benchmarking&lt;/h2&gt;&lt;p&gt;In service of the cooler project, my collection of these enterprise GPUs is nearly the full set from Kepler to Pascal. I have a few motherboards and CPUs that fit the bill as well to make a benchmarking effort worthwhile. These are the different hardware combinations I plan on trying:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GPUs&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;1x, 2x, 3x K80 (Will cause PCIe speed downgrades)&lt;/li&gt;&lt;li&gt;1x M10&lt;/li&gt;&lt;li&gt;1x M40&lt;/li&gt;&lt;li&gt;1x M60&lt;/li&gt;&lt;li&gt;1x M40 + 1x M60&lt;/li&gt;&lt;li&gt;1x P40&lt;/li&gt;&lt;li&gt;1x, 2x, 3x, 4x P100 (Will cause PCIe speed downgrades)&lt;/li&gt;&lt;li&gt;1x V100&lt;/li&gt;&lt;li&gt;1x V100 + 1x P100&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I’ll re-run the interesting results from the above sets of hardware on these different CPUs to see what changes:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;CPUs&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Intel Xeon E5-2687W v4 12-Core @ 3.00GHz (40 PCIe Lanes)&lt;/li&gt;&lt;li&gt;Intel Xeon E5-1680 v4 8-Core @ 3.40GHz (40 PCIe Lanes)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As for the actual tests, I’ll hopefully be able to come up with an ansible playbook that runs the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/homelab/comments/1j2k91l/comment/mfshipm/&quot;&gt;vLLM throughput with llama3-8b weights&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/homelab/comments/1j2k91l/comment/mfuj5i0/&quot;&gt;Folding@Home&lt;/a&gt;, &lt;a href=&quot;https://www.reddit.com/r/homelab/comments/1j2k91l/comment/mfx4rjc/&quot;&gt;BIONIC, Einstein@Home and Asteroids@Home&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/homelab/comments/1j2k91l/comment/mfsdfft/&quot;&gt;ai-benchmark.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/LocalAIServers/comments/1j2k3j3/comment/mfsg9y2/&quot;&gt;llama-bench&lt;/a&gt;&lt;/li&gt;&lt;li&gt;I’ll probably also write something to test raw &lt;a href=&quot;https://huggingface.co/docs/transformers/en/model_doc/vit&quot;&gt;ViT&lt;/a&gt; throughput as well.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Without running anything, I’d bet that all of this effort is going to tell us what we already know:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The later generation GPUs will perform better.&lt;/li&gt;&lt;li&gt;Adding more GPUs does increase performance but with diminishing returns.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Still though, I’d like to have some hard numbers before saying anything authoritatively.&lt;/p&gt;&lt;p&gt;All of this testing will also yield a lot of relevant data to the larger cooler project. One of the most complicated issues in the design is the process of going from the external temperature of the GPU to the internal core temperature. It is absolutely possible to model the relationship. Physical or numerical models, regression models, random forest models etc are all effective at doing the conversion. These methods require a lot of real-world data for training or testing. I’ve been harvesting this data for this purpose pretty much as long as I’ve run the compute cards in my lab:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/4-fan-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Archival photo of old temperature measurement setup.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/probe-1-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Probe thermistor attached with a 3D printed part. Didn&amp;#39;t work very well.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/ring-lug-1-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Washer thermistor - You would loose a bet about how poorly this performs.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/temperature-module-2-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;First iteration of standalone PCB for the temperature sensor.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This benchmarking project, as well as the subsequent server build with the winning config is a great source for this modeling data as well. In this direction, I made a harness to have each of the new coolers talk to the host via USB&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-163922-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Overview showing the cable routing piece installed on the open bench table.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-164202-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail shot of the cable routing.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250812-101622-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Printed piece.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The host also records &lt;code&gt;nvidia-smi&lt;/code&gt; output so all of the different variables can be compared on the same time series.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/m60_run.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;See you next time&lt;/h2&gt;&lt;p&gt;Unlike a lot of my posts, this one isn’t going to end with links to code or CAD. The cooler has come a long way since the original publication, but is still a work in progress. Regarding the Endgame EOL’d GPU Box, I’ll probably be developing the benchmark and running through the different configs &lt;a href=&quot;https://www.twitch.tv/esologic&quot;&gt;on stream&lt;/a&gt; this fall.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/08/20250729-122715-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;First batch of PCBs&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The post &lt;a href=&quot;https://esologic.com/new-cooler-first-look/&quot;&gt;First look at the New GPU Cooler Prototype&lt;/a&gt; appeared first on &lt;a href=&quot;https://esologic.com&quot;&gt;esologic&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>1kW of GPUs on the OpenBenchTable</title>
<link>https://esologic.com/1kw_openbenchtable/</link>
<guid isPermaLink="false">aGO21b4zN40_1ZKbEU0NLDIFInTJOKhdqdGR3w==</guid>
<pubDate>Mon, 13 Jul 2026 18:33:29 +0000</pubDate>
<description>In the conclusion of my previous homelab post, I pled to the eBay gods begging for a 4xP100 system. My prayers were heard, possibly by a malevolent spirit as a V100 16GB for $400 surfaced. More money than I’d be willing to spend on a P100 but the cheapest I’d ever seen a V100, I... The post 1kW of GPUs on the OpenBenchTable appeared first on esologic.</description>
<content:encoded>&lt;p&gt;In the conclusion of my previous homelab post, I &lt;a href=&quot;https://esologic.com/sliger-mods/#sliger-cx4200a-for-a-4x-tesla-p100-ollama-build&quot;&gt;pled to the eBay gods&lt;/a&gt; begging for a 4xP100 system. My prayers were heard, possibly by a malevolent spirit as a V100 16GB for $400 surfaced. More money than I’d be willing to spend on a P100 but the cheapest I’d ever seen a V100, I fell to temptation. To use all four cards, I needed something bigger than the Rosewill RSV-R4100U. Enter the OpenBenchTable, and some 3d printed parts I designed to be able to securely mount four compute GPUs:&lt;/p&gt;&lt;p&gt;OBT had been on my radar for a while and will serve as a great… test bench for work related to this computer. Amazingly, the manufacturers are honest about the Open part of the name and the CAD files for the chassis are freely available to download and build off of. The rest of the computer is the standard set of cheap and cheerful X99 parts:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Product&lt;/th&gt;&lt;th&gt;Price&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Motherboard&lt;/td&gt;&lt;td&gt;ASUS X99-E&lt;/td&gt;&lt;td&gt;$192.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CPU&lt;/td&gt;&lt;td&gt;Intel Xeon E5-1680 v4&lt;/td&gt;&lt;td&gt;$94.95&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CPU Cooler&lt;/td&gt;&lt;td&gt;Noctua NH-L9x65&lt;/td&gt;&lt;td&gt;$59.95&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Memory&lt;/td&gt;&lt;td&gt;4x 32GB DDR4&lt;/td&gt;&lt;td&gt;$94.95&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Power Supply&lt;/td&gt;&lt;td&gt;Corsair HX1500i 1500W&lt;/td&gt;&lt;td&gt;$147.70&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Case&lt;/td&gt;&lt;td&gt;OBT v2&lt;/td&gt;&lt;td&gt;$199.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Storage&lt;/td&gt;&lt;td&gt;1TB WD Blue NVMe&lt;/td&gt;&lt;td&gt;$54.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPU 1-3&lt;/td&gt;&lt;td&gt;P100 16GB&lt;/td&gt;&lt;td&gt;$360.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPU 4&lt;/td&gt;&lt;td&gt;V100 16GB&lt;/td&gt;&lt;td&gt;$400.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Total&lt;/td&gt;&lt;td&gt;$1,602.55&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Even though Ollama was invoked in the previous post, these days I’ve been back &lt;a href=&quot;https://esologic.com/introducing-gance/&quot;&gt;at my roots&lt;/a&gt; working on an AI image processing project. For the curious though, this box can do over 5 tokens/second on Deepseek R1 70B. I’ve done no optimization whatsoever and could actually &lt;a href=&quot;https://forum.level1techs.com/t/benchmarking-ai-box-performance/224086&quot;&gt;use some pointers&lt;/a&gt; on the best way to benchmark a system like this. Here are more photos of the build:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-154321-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Build overview showing coolers.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-153315-Display-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Only the PC on the bench.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-152430-Unknown-2025-1-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Build overview, system on the bench.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/0J9A9346-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Over 1kW pulled from the wall into the GPUs. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;I &lt;a href=&quot;https://www.twitch.tv/esologic&quot;&gt;livestreamed&lt;/a&gt; the migration of the system to the OpenBenchTable and the design of the PCIe bracket, here is that in 30 seconds:&lt;/p&gt;&lt;div&gt;&lt;video&gt;&lt;a href=&quot;https://esologic.com/wp-content/uploads/2025/03/migration_spedup_hq_2_noaudio.mp4&quot;&gt;https://esologic.com/wp-content/uploads/2025/03/migration_spedup_hq_2_noaudio.mp4&lt;/a&gt;&lt;/video&gt;&lt;/div&gt;&lt;h2&gt;PCIe Bracket Mount for OpenBenchTable&lt;/h2&gt;&lt;p&gt;The actual “project” here is the 3D printed PCIe bracket mount. Printed in PETG, this piece provides a significantly more rigid mounting surface to hold the GPUs in place. The OpenBenchTable ships with &lt;a href=&quot;https://openbenchtable.com/stock/&quot;&gt;4 long standoffs&lt;/a&gt;, plenty for the normal user but in my case about half as many as I actually needed. The power cables on the GPU are stiff, and want to yank the cards towards eachother. The result is the PCIe rod forms a long moment arm and the GPUs can easily wiggle around, potentially shorting out on their neighbor. The printed piece keeps neighboring cards separated and rigidly held in place.&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-155505-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Bracket mounted without GPUs. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-155518-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail shot of bracket to OBT mate using 18mm bolts. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-154931-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Bracket populated with GPUs.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-155311-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Bracket nut pockets.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-154845-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Printed &amp;quot;washer&amp;quot; holding brackets in place. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-153847-Display-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Print surface, note the use of supports.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-153917-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Support detail.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250227-153923-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Another support detail. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Like in pretty much all of my printed assemblies recently, I opt for nut pockets rather than threaded inserts here to keep things clean. When it’s quiet at night, I can hear my collection of hundreds of threaded inserts crying out from their parts bin on my shelf, pleading for attention. Eventually they’ll get used, but the nut pocket technique hasn’t let me down so far.&lt;/p&gt;&lt;p&gt;Honestly though, having now manufactured and assembled this piece, printed threads would probably do the job here.&lt;/p&gt;&lt;p&gt;I’ve published this part on &lt;a href=&quot;https://www.printables.com/model/1212906-openbenchtable-pcie-bracket-mount&quot;&gt;printables&lt;/a&gt;. It’s great that the STEP file for OBT v2 is available to build off of. I’m extremely happy to spend more on &lt;em&gt;any&lt;/em&gt; hardware product that comes with design files.&lt;/p&gt;&lt;p&gt;The BOM is really simple for this part:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91292A029/&quot;&gt;18mm M3 bolts&lt;/a&gt; for fixing the bracket to the OBT&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/90751A113/&quot;&gt;12mm M3 bolts&lt;/a&gt; and &lt;a href=&quot;https://www.mcmaster.com/90591A250/&quot;&gt;M3 nuts&lt;/a&gt; for fixing the GPU to the bracket.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Pico + Coolers&lt;/h2&gt;&lt;p&gt;You’ll notice a Raspberry Pi Pico mounted above the GPUs connecting to sensors on the outer surface of the center two cards. Maybe you’re also wondering about the 12 fans nested behind the cards as well.&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-154712-Bike-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Nested coolers.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2025/03/20250228-154943-Unknown-2025-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Top fans intake area.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This whole system is related to &lt;a href=&quot;https://esologic.com/cooler/&quot;&gt;another project&lt;/a&gt;, a follow up to my tesla cooler project from 2021. The interest from readers and my personal interest in that project has accelerated over the years initial publication, and I’ve been working to release a more powerful follow up that addresses the shortcomings with the design from that post.&lt;/p&gt;&lt;p&gt;If that is something you’re interested in, if quietly air-cooling many accelerator GPUs is a problem you have, leave a comment, send me an email (dev@esologic.com) or &lt;a href=&quot;https://esologic.com/follow-the-blog/&quot;&gt;follow the blog&lt;/a&gt; because there is going to be a lot more on this in the coming months and I need beta testers.&lt;/p&gt;&lt;p&gt;The post &lt;a href=&quot;https://esologic.com/1kw_openbenchtable/&quot;&gt;1kW of GPUs on the OpenBenchTable&lt;/a&gt; appeared first on &lt;a href=&quot;https://esologic.com&quot;&gt;esologic&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Hardware for Engineering Stream</title>
<link>https://esologic.com/stream-parts/</link>
<guid isPermaLink="false">c9qcZmqfm0DUIKZW0DR_QheKR1qMRkbLYLCWbw==</guid>
<pubDate>Mon, 13 Jul 2026 18:33:29 +0000</pubDate>
<description>My beloved blog post still sits on the throne as the most effective format for engineering projects. To me, Inlining code, photographs, CAD models and schematics in an interactive way trumps other mediums. This level of interactivity closes the gap between reader and material, allowing an independent relationship with the subject outside of the story... The post Hardware for Engineering Stream appeared first on esologic.</description>
<content:encoded>&lt;p&gt;My beloved blog post still sits on the throne as the most effective format for engineering projects. To me, Inlining code, photographs, CAD models and schematics in an interactive way trumps other mediums. This level of interactivity closes the gap between reader and material, allowing an independent relationship with the subject outside of the story being told by the author.&lt;/p&gt;&lt;p&gt;Working on stream to an online audience has a similar effect, the unedited and interactive format yielding a real understanding of the creators process and technique.&lt;/p&gt;&lt;p&gt;For a while there, I’d settled into a &lt;a href=&quot;https://esologic.com/tesla-cooler/#afterward&quot;&gt;nice habit&lt;/a&gt; of broadcasting project development live on &lt;a href=&quot;https://www.twitch.tv/esologic&quot;&gt;twitch&lt;/a&gt;. Two moves later, things have settled down enough in my personal life that I feel it’s time to try to get back into this habit.&lt;/p&gt;&lt;p&gt;Before we get started again, I took some time to improve the ergonomics (both hardware and software) of my stream setup. The following documents a few smaller projects, all in service of these upcoming broadcasts.&lt;/p&gt;&lt;h2&gt;RasRig&lt;/h2&gt;&lt;p&gt;Being able to capture the flow between the computer and the workbench is a critical requirement for engineering streams. This necessitates having a bunch of different cameras in a bunch of different places throughout the work space. In my case, I wanted a cost-effective way to have at least three different simultaneous shots of the bench. After some experimentation, I found that &lt;a href=&quot;https://github.com/jacksonliam/mjpg-streamer&quot;&gt;mjpg-streamer&lt;/a&gt; running on a Raspberry Pi using a camera connected via the CSI port can do a &lt;em&gt;great&lt;/em&gt; job of getting video into &lt;a href=&quot;https://obsproject.com/&quot;&gt;OBS&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Because video is transmitted over the network, it makes it easy to add cameras via my existing ethernet infrastructure or via WiFi, no need to route HDMI or SDI cables everywhere. Additionally, the ecosystem of CSI cameras is much larger than you’d think, as the NVidia Jetson boards are also compatible with the port. You can even get &lt;a href=&quot;https://www.amazon.com/Geekworm-Raspberry-TC358743-Supports-Compatible/dp/B09GY9M9BX/ref=sr_1_3?crid=1GMFCA8LIKGQZ&amp;amp;dib=eyJ2IjoiMSJ9.qYI8OhpXKANqYiX5BrtFTS-d7BOXV-FHYfmliuBwDtCiJl6kgkh9hkv0-KBbHTxxJzQ1qw8Bsoh8fWU4c-8LoslFThH-cLQRfdcWFknlicucnjmGjUHv5l9QDVYXrXPSVV8NJ6p8ncmEjOIFrU1WUheHIut5p6Od0cE3v4LyrGcFT8s5fh5dkxGXnLz0rTmW2JwXzjSTovB1606qlqHekRbZrjW_5ToVd3jO6iJ6vio.FFBw3KWrW60tAYMeESycdGGjsgOPjEzl77Z_sEpg8jU&amp;amp;dib_tag=se&amp;amp;keywords=csi%2Bhdmi&amp;amp;qid=1728241933&amp;amp;sprefix=csi%2Bhdmi%2Caps%2C117&amp;amp;sr=8-3&amp;amp;th=1&quot;&gt;HDMI capture cards that output into the CSI port&lt;/a&gt;, so HDMI cameras, or video inputs could be integrated.&lt;/p&gt;&lt;p&gt;In general, I’m fine with acquiring more pi-&lt;em&gt;ish&lt;/em&gt; hardware because I know it’ll get integrated into other projects should streaming become less desirable.&lt;/p&gt;&lt;h3&gt;Software&lt;/h3&gt;&lt;p&gt;Things like changing the resolution/FPS and exposure settings are also very easy to do because the Pi’s are networked. They’re also, well, Raspberry Pi’s. They have a practically infinite amount of expansion. Things like subject tracking, automatic exposure changing, alerting; all on the table for future projects. Ansible makes provisioning new cameras really simple, I’ve published the software to do this on &lt;a href=&quot;https://github.com/esologic/RasRig&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Mechanical Hardware&lt;/h3&gt;&lt;p&gt;Ansible is cool, but the CAD is the interesting bit at this stage. There are currently three different camera plates that support:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The standard Raspberry Pi camera module.&lt;/li&gt;&lt;li&gt;The Raspberry Pi HQ camera.&lt;/li&gt;&lt;li&gt;Those cheap OV5647 wide angle modules found on amazon.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There’s also a “plate” for use with massive c-mount microscope lenses as well. It’s easier to see these as a 3D render:&lt;/p&gt;&lt;p&gt;This is a single configuration using the Raspberry Pi 3B, and wide angle camera:&lt;/p&gt;&lt;p&gt;To start off my next series on stream, I’ve stood up three assemblies for three different camera angles.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;An ultra-wide angle establishing shot. This is a launch Raspberry Pi which works great.&lt;/li&gt;&lt;li&gt;Overhead bench camera.&lt;/li&gt;&lt;li&gt;Microscope camera.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The settings for these can be found in the &lt;a href=&quot;https://github.com/esologic/RasRig/blob/master/hosts.yml&quot;&gt;ansible hosts file in the repo&lt;/a&gt;. These are photos of the builds:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123240-Unknown-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;RasRig config, RPi 3B, with HQ camera and lens.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240924-092057-Portland-Usa-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of HQ camera.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123453-Unknown-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Another angle of rasrig config.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240924-092050-Portland-Usa-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of assembly.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240924-092039-Portland-Usa-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of Pi.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240924-092010-Portland-Usa-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Sloped edge allows access to GPIO pins, I use these for power.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240712_171224_B5BB125E-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Microscope config.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240712_171511_19CD4C76-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Huge microscope lens.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240712_171611_AC63A287-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Could also use smaller lenses with this setup.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240712_171323_20762864-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of tripod mount.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240920_190356_372BE820-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Launch Model B RasRig config.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/0J9A5836-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Wide angle lens installed.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240920-140412-Portland-Usa-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail showing the adapter plate. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For a while, in my previous setup, I was using the official raspberry Pi display as a microscope monitor. This is still supported by the hardware:&lt;/p&gt;&lt;p&gt;Here’s a photo of that setup:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/MG_6913-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h3&gt;RasRig Bill of Materials&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://www.printables.com/model/1029806-rasrig-a-system-to-mount-cameras-to-raspberry-pis&quot;&gt;All of the printed parts, for all configurations are available on Printables.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Depending on what configuration you choose, your hardware needs will be a bit different. Things are grouped here by physical component:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;pi-protector-switch-mount&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.digikey.com/en/products/detail/nkk-switches/M2012LL3W01/1046919&quot;&gt;The switch is a locking SPDT to power the Pi on and off.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/94180A321/&quot;&gt;M2.5 Threaded Inserts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You could use a M2.5 nut here if you don’t want to use the protector.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;plate-body&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/94180A333/&quot;&gt;6.4mm M3 Threaded Inserts for the three “bracing” bolts.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91292A316/&quot;&gt;Those “bracing” bolts are always M3x70mm in all camera plate configurations.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/94180A331/&quot;&gt;3.8mm M3 Threaded Inserts for the two front facing bolts.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The front facing bolts will change depending on your config.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/93365A160/&quot;&gt;0.3″ 1/4″-20 Threaded Inserts for the three tripod mounts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Camera Module&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt;In both the &lt;strong&gt;plate-camera-microscope&lt;/strong&gt; and &lt;strong&gt;plate-camera-short-downward-hq&lt;/strong&gt;, the same hardware is used to mount the camera to the printed piece.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91292A013/&quot;&gt;M2 x 20mm Bolts.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91828A111/&quot;&gt;M2 Nuts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;plate-camera-microscope-arm&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91292A020/&quot;&gt;The front facing bolts here are M3x25mm.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;plate-camera-module-or-wide-angle:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The camera module:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91292A833/&quot;&gt;M2x10mm Bolts fix camera to the plate.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/94180A307/&quot;&gt;M2 Threaded Inserts mate with those bolts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For the wide-angle camera module config:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/92290A846/&quot;&gt;M1.4x8mm Bolts fix the wide angle camera module to the plate.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/92120A140/&quot;&gt;M1.4 Threaded Inserts mate with those bolts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In both of these configs, and for the &lt;strong&gt;plate-camera-short-downward-hq&lt;/strong&gt; config, &lt;a href=&quot;https://www.mcmaster.com/91292A123/&quot;&gt;M3x20mm bolts&lt;/a&gt; are used.&lt;/p&gt;&lt;h2&gt;Desktop Microphone Stand&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123357-Unknown-2024-768x1152.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Stand with microphone installed.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925_173858_A377979B-768x1152.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Thread built into the anti-vibration mount.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925_173815_2556C308-768x1152.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;M8 bolt next to stand.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123707-Unknown-2024-scaled.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;M8 bolt installed.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is my second time designing and publishing a &lt;a href=&quot;https://www.thingiverse.com/thing:3093604&quot;&gt;desktop microphone stand&lt;/a&gt;. This time around for the &lt;a href=&quot;https://samsontech.com/products/microphones/condenser-microphones/c02/&quot;&gt;Samson C02&lt;/a&gt; condenser microphone. The microphone ships with a shock mount that has a 5/8″-27 thread in the bottom, which is large enough to be 3D printable. The rod with the thread mates with a base using a big ‘ol &lt;a href=&quot;https://www.mcmaster.com/91290A470/&quot;&gt;M8x110mm bolt&lt;/a&gt; that also adds rigidity. Pretty simple!&lt;/p&gt;&lt;p&gt;During the stream, this mic will sit on the bench, so I can switch between the two spots without having the go grabbing for another microphone.&lt;/p&gt;&lt;p&gt;The XLR cable for the mic is the only new run between my computer workstation and the bench. It plugs into the USB sound interface I use, along with the other CO2 that is used as the desktop mic. The software stack for the microphones is a bit indirect:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://sourceforge.net/projects/equalizerapo/&quot;&gt;Equalizer APO&lt;/a&gt; is installed, used for modifying the input audio.&lt;/li&gt;&lt;li&gt;The software preamp built into Equalizer APO is used to boost the input sound level, which is a bit quiet out of the interface.&lt;/li&gt;&lt;li&gt;An &lt;a href=&quot;https://github.com/werman/noise-suppression-for-voice&quot;&gt;AI noise reduction plugin&lt;/a&gt; removes hiss and self-noise and room noise. The resulting audio quality is good enough, and I really would like to avoid a massive SM7B-style microphone.&lt;/li&gt;&lt;li&gt;Audio from the mics flows through the &lt;a href=&quot;https://sourceforge.net/projects/peace-equalizer-apo-extension/&quot;&gt;Peace Plugin&lt;/a&gt;, EQ-ing the sound.&lt;/li&gt;&lt;li&gt;Then, in OBS, I create two mono audio sources based on the two halves of the interface.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I’d like to have a compressor to prioritize voice audio over desktop audio for the stream, but I haven’t gotten that far yet.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.printables.com/model/1029849-desktop-microphone-stand&quot;&gt;The printable pieces for this Desktop Microphone Stand are available on Printables.&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;C-Stand Workbench Mount&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930_175906_F75526CE-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;C-Stand with light, low over the workbench.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/Pole-Mounted-Cropped-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;C-Stand mounted to bench.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-122709-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of bench mount.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-122738-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Six 50mm bolts lock things in place.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-114008-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of bench mount piece.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-114003-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of bench mount piece.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-113944-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of outer piece.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-122841-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Stabilizer and foot. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-122837-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of stabilizer.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-122823-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Outer piece re-used for stabilizer.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-113859-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of captive M3 nuts.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-113843-Office-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Detail of stabilizer.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-113915-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Used to retain stabilizer using friction.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-114257-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Foot detail.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-114422-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Foot detail, retaining pin still works!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930-114345-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;More of the retaining pin.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This has been a wishlist project of mine since I moved into this apartment. I bought this &lt;a href=&quot;https://www.flashpointlighting.com/product/flashpoint-10-c-stand-on-turtle-base-kit-40-grip-arm-two-3-gobo-heads/&quot;&gt;c-stand&lt;/a&gt; several years ago and have gotten so much use out of it ever since. It’s big, it’s heavy and it has no problem performing non-photography related tasks. I’ve used it to hold lights, microphones, cameras, cooling fans and photo backdrops.&lt;/p&gt;&lt;p&gt;However, my new space is pretty small, and I don’t have the floor space for the legs.&lt;/p&gt;&lt;p&gt;This design essentially removes the need for the “turtle base” (the legs), bolting the base directly to the workbench. There’s a strong chance I make another one of these for the other side of the bench later on, I’m loving this that much.&lt;/p&gt;&lt;p&gt;This is kind of hard to photograph, here’s the 3D model I used:&lt;/p&gt;&lt;p&gt;This will light the shots provided by the overhead RasRig cameras during stream, and gives me a ton of flexibility to be able to change out lights and increase/decrease intensity as needed.&lt;/p&gt;&lt;p&gt;For mechanical hardware:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91290A137/&quot;&gt;M3x50mm Bolts.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91828A211/&quot;&gt;M3 Nuts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Are used by the printed pieces to fix the pole in place.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/90666A140/&quot;&gt;M8x30mm bolts fix the stabilizer to the bench.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/90591A161/&quot;&gt;M8 Nuts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://www.printables.com/model/1029837-c-stand-workbench-mount&quot;&gt;This is pretty specific to my setup, but if you’d like to print your own the files are on Printables.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Sadly, this new lighting setup forced my old desk lamp into retirement. To commemorate his many years of fantastic work, I built him a new perch where he can enjoy his twilight years as an overhead lamp.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20241001_215554_64858F3A-300x200.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20241001_215535_FE717B9D-300x200.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;Articulating Ball Head Arm&lt;/h2&gt;&lt;p&gt;Frustratingly, you can’t really buy separate arms without the desk mounting poles for &lt;a href=&quot;https://www.amazon.com/gp/product/B08LV7GZVB/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;amp;th=1&quot;&gt;desk-mount arm kits commonly found on amazon&lt;/a&gt;. I use the arm that came with this kit for the microscope camera described above, but I wanted to add another arm to hold the other overhead camera. These overhead bench shots add a lot of depth to the stream.&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240923-112030-Portrait-Portland-2024-scaled-e1728179439911-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123500-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123515-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240925-123521-Unknown-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240923-112101-Portland-Usa-2024-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930_180051_866B054E-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img src=&quot;https://esologic.com/wp-content/uploads/2024/10/20240930_175906_F75526CE-768x512.jpg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href=&quot;https://www.amazon.com/dp/B0B5WTPVH7?psc=1&amp;amp;ref=ppx_yo2ov_dt_b_product_details&quot;&gt;ball head&lt;/a&gt; I use is a bit overkill, but again it’s something I know I can re-use very easily down the road.&lt;/p&gt;&lt;p&gt;The hardware here is really simple:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/90128A266/&quot;&gt;A M6x30mm Bolt for the pole arm.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/91502A177/&quot;&gt;M6x65mm Bolts link the arms together.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.mcmaster.com/94300A330/&quot;&gt;M6 Wing Nuts fasten all the bolts.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://www.printables.com/model/1029872-articulating-ball-head-arm&quot;&gt;Printed parts again are on Printables.&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Stream Demo!&lt;/h2&gt;&lt;p&gt;So how does this all look? I shot a context video for the project I’m going to be working on first on the stream:&lt;/p&gt;&lt;p&gt;I’m still not 100% happy with the audio pipeline, and I think I’d like to get a macropad for scene switching but I think we’re good to go.&lt;/p&gt;&lt;p&gt;The post &lt;a href=&quot;https://esologic.com/stream-parts/&quot;&gt;Hardware for Engineering Stream&lt;/a&gt; appeared first on &lt;a href=&quot;https://esologic.com&quot;&gt;esologic&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
</channel>
</rss>
