<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TechFuel HQ</title><link>https://techfuelhq.com/</link><description>Recent content on TechFuel HQ</description><generator>Hugo</generator><language>en-us</language><managingEditor>LK Wood IV</managingEditor><lastBuildDate>Tue, 18 Aug 2026 03:30:00 -0500</lastBuildDate><atom:link href="https://techfuelhq.com/index.xml" rel="self" type="application/rss+xml"/><atom:link href="https://pubsubhubbub.appspot.com/" rel="hub"/><item><title>Best Motherboards for Ryzen 7 9800X3D (2026)</title><link>https://techfuelhq.com/articles/best-motherboard-ryzen-7-9800x3d-2026/</link><pubDate>Tue, 18 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/best-motherboard-ryzen-7-9800x3d-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-18 · 14 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="the-three-boards-at-a-glance">The three boards at a glance&lt;/h2>
&lt;p>The 9800X3D reaches full gaming speed on a well-built mainstream board. These picks buy three different layouts; CPU performance stays in the same class, so every dollar above the B850 default must purchase a port, lane, form factor, debug control, or expansion path the build will use.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Pick&lt;/th>
&lt;th scope="col">Best for&lt;/th>
&lt;th scope="col">The features that justify it&lt;/th>
&lt;th scope="col" style="text-align: right">Aug. 17 reference&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>MSI MAG B850 Tomahawk Max WiFi&lt;/strong>&lt;/td>
&lt;td>Best ATX value for most builds&lt;/td>
&lt;td>PCIe 5.0 x16, Gen5 M.2, Wi-Fi 7, 5GbE, strong 80A-stage listing&lt;/td>
&lt;td style="text-align: right">&lt;strong>$209.99 standalone&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ASUS ROG Strix B850-G Gaming WiFi&lt;/strong>&lt;/td>
&lt;td>White micro-ATX build&lt;/td>
&lt;td>Four M.2, Wi-Fi 7, 2.5GbE, 20Gbps USB-C, PCIe 5.0 x16&lt;/td>
&lt;td style="text-align: right">ASUS listed &lt;strong>$259.99&lt;/strong> standalone; bundle was $1,059.99&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ASUS ROG Crosshair X870E Hero&lt;/strong>&lt;/td>
&lt;td>Storage, USB4, and expansion-heavy build&lt;/td>
&lt;td>Five M.2, SlimSAS, dual USB4, 5GbE + 2.5GbE, Wi-Fi 7&lt;/td>
&lt;td style="text-align: right">ASUS listed &lt;strong>$569.99&lt;/strong> standalone; bundle was $1,599.99&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>The standalone MSI price is a dated Newegg feed snapshot. The ASUS figures came from the official product-page offers captured on August 18. The bundle figures are current retailer snapshots described later. Check the live number before ordering.&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/best-motherboard-ryzen-7-9800x3d-2026.svg" alt="Ryzen 7 9800X3D motherboard decision map. A B850 board covers the gaming essentials and is marked the default. A white micro-ATX B850 branch serves compact aesthetic builds. An X870E branch adds five M.2 slots, USB4, dual wired networking, and extra lane flexibility for expansion-heavy systems." width="1200" height="630" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="the-rule-that-prevents-motherboard-overspending">The rule that prevents motherboard overspending&lt;/h2>
&lt;p>Buy the cheapest well-built board that has the ports you will use. Then verify its slot and lane map. Write those requirements down before opening retailer tabs; otherwise every extra feature looks useful in isolation.&lt;/p>
&lt;p>The Ryzen 7 9800X3D is an eight-core, 120W AM5 processor. A decent B850 board already supplies ample CPU power. Moving to X870 or X870E changes the connectivity floor and lane layout; it does not add gaming frames by itself.&lt;/p>
&lt;p>I would reject a board for:&lt;/p>
&lt;ul>
&lt;li>no BIOS Flashback on an expensive build&lt;/li>
&lt;li>weak rear I/O for the devices you own&lt;/li>
&lt;li>only gigabit Ethernet when faster networking matters&lt;/li>
&lt;li>a lane-sharing rule that disables a card or drive you plan to install&lt;/li>
&lt;li>too few M.2 slots for the build&amp;rsquo;s life&lt;/li>
&lt;li>a price that approaches premium X870E territory without premium I/O&lt;/li>
&lt;/ul>
&lt;p>A lower chipset rung does not disqualify a board. A missing port or broken lane plan does.&lt;/p>
&lt;h2 id="1-msi-b850-tomahawk-max-wifi-is-the-default">1. MSI B850 Tomahawk Max WiFi is the default&lt;/h2>
&lt;p>The B850 Tomahawk Max WiFi is the board I would put under a 9800X3D gaming system unless the build brief names a reason to move. That reason should be concrete: a smaller white case, five NVMe drives, USB4 peripherals, or an add-in-card layout this board cannot serve.&lt;/p>
&lt;p>The exact Newegg row lists:&lt;/p>
&lt;ul>
&lt;li>ATX form factor&lt;/li>
&lt;li>B850 chipset and AM5 socket&lt;/li>
&lt;li>PCIe 5.0 x16&lt;/li>
&lt;li>a Gen5 M.2 slot&lt;/li>
&lt;li>Wi-Fi 7&lt;/li>
&lt;li>5GbE&lt;/li>
&lt;li>four DDR5 slots&lt;/li>
&lt;li>four SATA ports&lt;/li>
&lt;li>an 80A smart-power-stage design&lt;/li>
&lt;/ul>
&lt;p>That is the useful part of a modern high-end platform without a flagship tax. The August 17 feed captured $209.99 against a $229.99 regular field. Even if the live price moves, the board belongs in the low-$200 class. A $500 board serves a different build.&lt;/p>
&lt;p>There is one layout caveat in the retailer specification: the lower PCIe 4.0 x4-length slot drops to x2 when M.2_3 is populated. If you plan to run a fast capture card, storage adapter, or 10GbE NIC there, read the manual before filling every M.2 slot. Gaming builds with one GPU will rarely care. Hybrid workstation and homelab builds can care immediately.&lt;/p>
&lt;p>For a gaming tower with one GPU, two or three NVMe drives, and onboard networking, this is the complete answer.&lt;/p>
&lt;h2 id="2-rog-strix-b850-g-is-the-white-micro-atx-pick">2. ROG Strix B850-G is the white micro-ATX pick&lt;/h2>
&lt;p>The B850-G exists for a different build. It compresses a premium-looking white AM5 platform into micro-ATX without stripping the storage and rear I/O that usually disappear first.&lt;/p>
&lt;p>ASUS specifies:&lt;/p>
&lt;ul>
&lt;li>micro-ATX&lt;/li>
&lt;li>14+2+1 power stages&lt;/li>
&lt;li>PCIe 5.0 x16&lt;/li>
&lt;li>four M.2 slots, including one Gen5 slot&lt;/li>
&lt;li>Wi-Fi 7&lt;/li>
&lt;li>Intel 2.5GbE&lt;/li>
&lt;li>ten rear USB ports, led by 20Gbps Type-C&lt;/li>
&lt;li>BIOS Flashback and Clear CMOS buttons&lt;/li>
&lt;/ul>
&lt;p>The fourth M.2 slot sits on the underside, which matters for access and cooling. Two SATA ports are also lean for anyone reusing several 2.5-inch drives. Those layout costs should be in the case plan. Install the underside SSD before the board goes into the chassis; discovering it later turns a two-minute upgrade into a teardown.&lt;/p>
&lt;p>ASUS&amp;rsquo;s page listed $259.99 at capture. That premium over the MSI buys a smaller white board and its particular I/O arrangement. It does not buy a faster 9800X3D.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/deeplink?id=CW4UrCo/56I&amp;amp;mid=44583&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fp%2Fpl%3Fd%3DASUS%2BROG%2BStrix%2BB850-G%2BGaming%2BWiFi"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="search">Search Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="3-crosshair-x870e-hero-is-for-expansion">3. Crosshair X870E Hero is for expansion&lt;/h2>
&lt;p>The Crosshair X870E Hero is not the &amp;ldquo;best gaming&amp;rdquo; choice. It is the choice for a system that needs to behave like a workstation while keeping an X3D gaming CPU.&lt;/p>
&lt;p>Its reason to exist is the I/O map:&lt;/p>
&lt;ul>
&lt;li>five M.2 slots, three of them Gen5 with a Ryzen 9000 or 7000 processor&lt;/li>
&lt;li>SlimSAS plus four SATA ports&lt;/li>
&lt;li>two USB4 40Gbps rear ports&lt;/li>
&lt;li>eight additional 10Gbps rear USB ports&lt;/li>
&lt;li>5GbE and 2.5GbE&lt;/li>
&lt;li>Wi-Fi 7&lt;/li>
&lt;li>two full-length CPU-connected slots with configurable lane sharing&lt;/li>
&lt;li>onboard Q-Code, start controls, BIOS Flashback, and Clear CMOS&lt;/li>
&lt;/ul>
&lt;p>The lane-sharing rules deserve attention. Populate the second and third CPU-connected M.2 slots and the primary graphics slot can fall to x8 while the second full-length slot changes or disables. That is normal on a feature-dense desktop platform, but it means the installation order needs a plan. Sketch the final drive and card map first. Buying five slots is useless if populating the wrong two breaks the slot you bought the board to gain.&lt;/p>
&lt;p>ASUS listed $569.99 at capture. Spend that only when the five-drive layout, USB4, dual wired networking, or slot flexibility replaces hardware you would otherwise add. A single-GPU gaming PC with two drives does not need it.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/deeplink?id=CW4UrCo/56I&amp;amp;mid=44583&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fp%2Fpl%3Fd%3DASUS%2BROG%2BCrosshair%2BX870E%2BHero"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="search">Search Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="b850-vs-x870-vs-x870e-for-the-9800x3d">B850 vs X870 vs X870E for the 9800X3D&lt;/h2>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Chipset class&lt;/th>
&lt;th scope="col">Buy it when&lt;/th>
&lt;th scope="col">Do not buy it for&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>B850&lt;/strong>&lt;/td>
&lt;td>One GPU, normal NVMe count, gaming-first value&lt;/td>
&lt;td>More FPS from the CPU&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>X870&lt;/strong>&lt;/td>
&lt;td>You want USB4 and a stronger modern-I/O baseline&lt;/td>
&lt;td>A belief that &amp;ldquo;X&amp;rdquo; means faster games&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>X870E&lt;/strong>&lt;/td>
&lt;td>You need more high-speed expansion and can map the lanes&lt;/td>
&lt;td>One GPU, two drives, and no add-in cards&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>AMD&amp;rsquo;s AM5 chipset table is the right starting point, but a model&amp;rsquo;s manual is the final authority. Two boards with the same chipset can expose different slots and controllers. Their sharing rules can differ too.&lt;/p>
&lt;p>That is why the shortlist crosses chipset tiers. It follows build requirements.&lt;/p>
&lt;h2 id="are-the-cpu-bundles-worth-it">Are the CPU bundles worth it?&lt;/h2>
&lt;p>The August feed contained several Ryzen 7 9800X3D motherboard bundles. Three illustrate why &amp;ldquo;bundle&amp;rdquo; is not a synonym for &amp;ldquo;deal.&amp;rdquo;&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Bundle&lt;/th>
&lt;th scope="col" style="text-align: right">Aug. 17 snapshot&lt;/th>
&lt;th scope="col">Rendered seller check, Aug. 18&lt;/th>
&lt;th scope="col">What to verify&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Sapphire NITRO+ B850M + 9800X3D&lt;/td>
&lt;td style="text-align: right">&lt;strong>$969.99&lt;/strong>&lt;/td>
&lt;td>TECH EDGE; new; ships from China; not fulfilled by Newegg&lt;/td>
&lt;td>Manufacturer warranty flag was false; returns were non-replaceable&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ASUS ROG Strix B850-G + 9800X3D&lt;/td>
&lt;td style="text-align: right">&lt;strong>$1,059.99&lt;/strong>&lt;/td>
&lt;td>TECH EDGE; new; ships from China; not fulfilled by Newegg&lt;/td>
&lt;td>Manufacturer warranty flag was true; still compare return freight and delivery&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ASUS Crosshair X870E Hero + 9800X3D&lt;/td>
&lt;td style="text-align: right">&lt;strong>$1,599.99&lt;/strong>&lt;/td>
&lt;td>TECH EDGE; new; ships from China; not fulfilled by Newegg&lt;/td>
&lt;td>Manufacturer warranty flag was true; the premium only works if you need the board&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>The seller was rated 4.6/5 over 39 reviews in the prior 12 months and marked Top Rated in the embedded listing data at capture. That is useful context. It is not the same purchase path as a direct Newegg item. A heavy motherboard-and-CPU return to China can consume the paper discount in freight and delay. It also adds transit risk.&lt;/p>
&lt;p>Price the CPU and board separately first. Newegg&amp;rsquo;s exact 9800X3D row was $479 in the same feed. Add the $209.99 MSI board and the parts total is $688.99 before tax. A $969.99 micro-ATX bundle therefore needs to justify roughly $281 through a different board, availability, or terms. The Crosshair bundle is a specialist purchase rather than a value shortcut.&lt;/p>
&lt;p>If you still want a bundle, use the current searches below and inspect the exact seller block before payment.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/deeplink?id=CW4UrCo/56I&amp;amp;mid=44583&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fp%2Fpl%3Fd%3DRyzen%2B7%2B9800X3D%2Bmotherboard%2Bbundle"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="search">Search Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="what-about-b650-and-x670">What about B650 and X670?&lt;/h2>
&lt;p>You do not need to replace a good AM5 board merely because B850 and X870 exist.&lt;/p>
&lt;p>If you already own B650, B650E, X670, or X670E, check the manufacturer&amp;rsquo;s 9800X3D BIOS support and the ports you need. A supported existing board is usually the value winner. The &lt;a href="https://techfuelhq.com/reviews/rog-strix-b650a-review-2026/">ROG Strix B650-A review&lt;/a> covers one real example of a B650 board running an X3D system with ample power delivery.&lt;/p>
&lt;p>Before a BIOS update, back up important data and do not interrupt power during the flash. Use BIOS Flashback when the board supports it and the installed CPU cannot boot the current firmware.&lt;/p>
&lt;p>This page covers a new board purchase. A working compatible platform should stay in service.&lt;/p>
&lt;h2 id="ram-cooling-and-the-rest-of-the-build">RAM, cooling, and the rest of the build&lt;/h2>
&lt;p>Use two DDR5 modules. DDR5-6000 with an AMD EXPO profile is the low-drama target; the &lt;a href="https://techfuelhq.com/articles/ddr5-ram-buying-guide-2025/">DDR5 buying guide&lt;/a> explains why a larger advertised number is not automatically a better AM5 result. For the purchase itself, use the &lt;a href="https://techfuelhq.com/data/ram-price-index/">open RAM price index&lt;/a>: its August 18 capture reviewed 583 listings, still found only three of 12 tracked kits that cleared the direct-retailer rules, and put the cheapest qualifying 32GB observation at $459.99. The gate remains closed, so treat the table as dated offers rather than a broad market average.&lt;/p>
&lt;p>The 9800X3D does not include a cooler. Board selection should therefore leave room in the case and budget for the cooling hardware you want. The board does not need a giant VRM heatsink to survive this CPU, but the case still needs airflow across the socket, memory, SSD heatsinks, and graphics card. Header placement matters here: count pump and fan headers against the actual radiator and case layout, rather than assuming a premium board has one in the convenient corner.&lt;/p>
&lt;p>One build can overturn the entire default. Imagine a 9800X3D workstation with an RTX 5080, three Gen5 scratch drives, two more archive SSDs, a capture card, 10GbE today, and a USB4 RAID enclosure already on the desk. The Crosshair&amp;rsquo;s price is suddenly easier to defend because one board replaces an add-in network card, a storage adapter, and a Thunderbolt-style expansion plan. Remove those devices and the logic collapses back to B850. That is the standard: every premium interface should displace another cost or solve a named constraint. The workstation case can defend the X870E premium because its five-drive map, USB4 enclosure, faster wired links, debug controls, and second expansion slot replace a pile of adapters while keeping the build coherent; a one-GPU gaming tower with two SSDs receives none of that value, even though both machines use the same processor and can post the same frame rate. Run the same test in reverse before paying: remove USB4, the fifth drive, the second network link, and the extra card from the parts plan; if the system still works exactly as intended, the premium board has lost every job that made it rational and the B850 choice is stronger.&lt;/p>
&lt;p>Finally, map the whole build before checkout:&lt;/p>
&lt;ul>
&lt;li>exact case form factor&lt;/li>
&lt;li>GPU thickness and slot obstruction&lt;/li>
&lt;li>number of M.2 and SATA drives&lt;/li>
&lt;li>front USB-C header requirement&lt;/li>
&lt;li>wired network speed&lt;/li>
&lt;li>add-in cards now and later&lt;/li>
&lt;li>fan and pump-header count&lt;/li>
&lt;/ul>
&lt;p>The &lt;a href="https://techfuelhq.com/tools/pc-builder/">PC Builder&lt;/a> catches the basic socket and form-factor problems. Its &lt;a href="https://techfuelhq.com/data/pc-part-prices-2026/">open 126-part compatibility dataset&lt;/a> exposes the source and last-verified date behind each supported row. The board manual catches the lane-sharing rules that a category-level dataset cannot.&lt;/p>
&lt;h2 id="the-shortest-honest-recommendation">The shortest honest recommendation&lt;/h2>
&lt;p>Buy the &lt;strong>MSI B850 Tomahawk Max WiFi&lt;/strong> for a normal ATX 9800X3D gaming build.&lt;/p>
&lt;p>Buy the &lt;strong>ROG Strix B850-G&lt;/strong> when the machine must be white and micro-ATX.&lt;/p>
&lt;p>Buy the &lt;strong>Crosshair X870E Hero&lt;/strong> only when five M.2 slots, USB4, dual wired networking, or its expansion controls are already part of the plan.&lt;/p>
&lt;p>Anything beyond that is paying for a feature list you have not assigned a job.&lt;/p></description></item><item><title>Best RTX 5080 Prebuilt Gaming PCs (2026)</title><link>https://techfuelhq.com/articles/best-rtx-5080-prebuilt-gaming-pc-2026/</link><pubDate>Tue, 18 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/best-rtx-5080-prebuilt-gaming-pc-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-18 · 13 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="the-three-picks-at-a-glance">The three picks at a glance&lt;/h2>
&lt;p>All three finalists use the same performance core: Ryzen 7 9800X3D, GeForce RTX 5080 16GB, 32GB DDR5, and a 2TB NVMe SSD. The table therefore ranks what usually stays hidden in a prebuilt listing.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Pick&lt;/th>
&lt;th scope="col">Why it made the list&lt;/th>
&lt;th scope="col" style="text-align: right">Disclosed power supply&lt;/th>
&lt;th scope="col" style="text-align: right">Newegg feed snapshot, Aug. 17&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>ABS Kaze II Ruby&lt;/strong>&lt;/td>
&lt;td>Best disclosed parts list and power hardware&lt;/td>
&lt;td style="text-align: right">Gamdias HELIOS P2-1000G, 1000W Gold&lt;/td>
&lt;td style="text-align: right">&lt;strong>$2,939.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Andromeda Insights V3 Ultra 50&lt;/strong>&lt;/td>
&lt;td>Best value; explicitly lists DDR5-6000 and an 850W Gold supply&lt;/td>
&lt;td style="text-align: right">850W Gold, brand not stated&lt;/td>
&lt;td style="text-align: right">&lt;strong>$2,799.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Acer Nitro UD.P02AA.070&lt;/strong>&lt;/td>
&lt;td>Brand-name alternative with liquid cooling&lt;/td>
&lt;td style="text-align: right">850W, efficiency and model not stated&lt;/td>
&lt;td style="text-align: right">&lt;strong>$3,299.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>Those prices are dated retailer-feed snapshots. The exact Newegg pages still resolved to the matching item on August 18, and all three pages showed Newegg as both seller and shipper at capture. Inventory can move before this page does.&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/best-rtx-5080-prebuilt-gaming-pc-2026.svg" alt="RTX 5080 prebuilt buying diagram showing that the GPU and CPU are only the visible layer; the decision is made by four hidden checks: a named 850W-or-better power supply, two memory modules, a 2TB SSD, and a clear seller, warranty, and return path" width="1200" height="630" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="how-i-ranked-the-systems">How I ranked the systems&lt;/h2>
&lt;p>I started with a hard floor, then let disclosed component quality break the tie. A product page that names the PSU model, memory arrangement, storage generation, board, and seller path can justify a modest premium because each disclosed field removes a return-window investigation; a page that repeats only the CPU and GPU cannot.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>RTX 5080 16GB and Ryzen 7 9800X3D.&lt;/strong> A cheaper processor can still run a 5080, but it is less hardware at this price. Every finalist uses AMD&amp;rsquo;s eight-core X3D chip.&lt;/li>
&lt;li>&lt;strong>32GB DDR5 and 2TB NVMe.&lt;/strong> A $3,000 gaming PC should not arrive with 16GB or a cramped 1TB system drive.&lt;/li>
&lt;li>&lt;strong>At least 850W.&lt;/strong> NVIDIA lists 850W minimum system power for the 360W RTX 5080. The &lt;a href="https://techfuelhq.com/articles/what-psu-for-rtx-5080-2026/">full RTX 50-series PSU guide&lt;/a> explains when 1000W becomes the better buy.&lt;/li>
&lt;li>&lt;strong>A listing that names the weak links.&lt;/strong> PSU model, memory speed, motherboard, cooler, seller, and warranty matter. Silence is a risk, not a premium feature.&lt;/li>
&lt;li>&lt;strong>The title, item number, and destination had to agree.&lt;/strong> I discarded feed rows whose product name and Newegg URL described different hardware.&lt;/li>
&lt;/ol>
&lt;p>RGB earned zero points. A giant discount badge against a price the system may never have sold for earned zero too.&lt;/p>
&lt;h2 id="1-abs-kaze-ii-ruby-has-the-strongest-disclosed-parts-list">1. ABS Kaze II Ruby has the strongest disclosed parts list&lt;/h2>
&lt;p>The Kaze II Ruby wins because its parts list answers the most expensive hidden question. Newegg names the power supply as a &lt;strong>Gamdias HELIOS P2-1000G 1000W 80 Plus Gold&lt;/strong> unit. That changes the decision: the other two finalists list capacity, but they never identify the complete model.&lt;/p>
&lt;p>The rest is the right shape for a high-end gaming system:&lt;/p>
&lt;ul>
&lt;li>Ryzen 7 9800X3D&lt;/li>
&lt;li>RTX 5080 16GB&lt;/li>
&lt;li>32GB DDR5&lt;/li>
&lt;li>2TB PCIe NVMe SSD&lt;/li>
&lt;li>Wi-Fi 6&lt;/li>
&lt;li>Windows 11 Home&lt;/li>
&lt;/ul>
&lt;p>The August 17 feed showed $2,939.99, down from a listed $3,499.99 regular figure. I care more about the $2,939.99 checkout number than the size of that markdown. The flashy percentage badge can disappear tomorrow; the named power supply is still the hardware inside the case.&lt;/p>
&lt;p>There are still three checks to make. Confirm the 32GB arrives as two modules, identify the motherboard, and read the current warranty and return language. A named PSU does not make every undisclosed part disappear. It does make this the easiest system to approve. If the checkout configuration swaps any of those fields, stop and re-price the machine.&lt;/p>
&lt;h2 id="2-andromeda-v3-ultra-50-is-the-value-pick">2. Andromeda V3 Ultra 50 is the value pick&lt;/h2>
&lt;p>The Andromeda was the least expensive qualified system in the feed at $2,799.99. It also discloses more memory detail than the other listings: &lt;strong>32GB of DDR5-6000&lt;/strong>. The 2TB drive is described as Gen4, and the power supply is rated 850W Gold.&lt;/p>
&lt;p>That is a strong specification sheet for $140 less than the ABS. The trade is confidence around the power supply. &amp;ldquo;850W Gold&amp;rdquo; tells you the capacity and efficiency tier; it does not identify the platform, protections, cable, or warranty. NVIDIA&amp;rsquo;s 850W floor means the capacity is sufficient. The missing model is why this system finishes second. Ask for the exact unit before the return window closes; a photo of the side label settles it in seconds.&lt;/p>
&lt;p>The exact page showed the matching Andromeda title. Newegg handled both the sale and shipment from the United States when checked. That removes the marketplace ambiguity that sinks many cheaper-looking results.&lt;/p>
&lt;p>Buy this one when the price gap matters and the listing or support team can provide the exact PSU and memory configuration before the return window closes.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.445834222291073233416867&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fandromeda-insights-ultra-gaming-desktop-pcs-geforce-rtx-5080-amd-ryzen-7-9800x3d-32gb-ddr5-2tb-nvme-ssd-50-vector-black%2Fp%2F3D5-006J-00058%3Fitem%3D3D5-006J-00058"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="3-acer-nitro-is-the-brand-name-alternative">3. Acer Nitro is the brand-name alternative&lt;/h2>
&lt;p>Acer&amp;rsquo;s Nitro UD.P02AA.070 keeps the same core specification and adds liquid CPU cooling. The listing names a Ryzen 7 9800X3D, RTX 5080 16GB, 32GB DDR5, 2TB PCIe NVMe SSD, and an 850W power supply.&lt;/p>
&lt;p>It also asks the most. The feed captured $3,299.99, which is $360 above the ABS and $500 above the Andromeda. The listing does not name the PSU model or efficiency certification, and it specifies gigabit Ethernet rather than a faster wired interface.&lt;/p>
&lt;p>That does not make the Acer a bad machine. It makes the premium hard to defend from the published parts list alone. Choose it if the exact Acer service package, local availability, or chassis design has value to you. On hardware disclosure per dollar, it ranks third. At this price, brand familiarity needs to arrive with a better support path, not merely a familiar badge.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.445836957457544655962378&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Facer-america-nitro-acer-r7-9800x3d-rtx-5080-16g-32gb-ram-2tb-ssd-liquid-cooling-gaming-pc-win11-geforce-rtx-5080-amd-ryzen-7-9800x3d-32gb-ddr5-2tb-pcie-nvme-ssd-ud-p02aa-070%2Fp%2FN82E16883101948%3Fitem%3DN82E16883101948"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="what-i-rejected">What I rejected&lt;/h2>
&lt;p>The live search results contain dozens of RTX 5080 systems. Most fail for one of five reasons.&lt;/p>
&lt;h3 id="a-lower-tier-cpu-at-the-same-system-price">A lower-tier CPU at the same system price&lt;/h3>
&lt;p>A Core i7-14700F or Ryzen 7 9700X can be a good processor. It does not belong in a system priced beside these 9800X3D builds unless the rest of the machine is materially better.&lt;/p>
&lt;h3 id="sixteen-gigabytes-of-system-memory">Sixteen gigabytes of system memory&lt;/h3>
&lt;p>That is an immediate upgrade on a new flagship PC. It also raises the chance of a single-module configuration. Thirty-two gigabytes is the floor here.&lt;/p>
&lt;h3 id="one-terabyte-of-storage">One terabyte of storage&lt;/h3>
&lt;p>Modern game libraries fill it quickly. A 2TB system drive is a modest requirement at this budget, and all three picks meet it.&lt;/p>
&lt;h3 id="a-vague-or-undersized-power-supply">A vague or undersized power supply&lt;/h3>
&lt;p>The RTX 5080&amp;rsquo;s official requirement is 850W system power. A listing below that floor is out. A listing that says only &amp;ldquo;1000W&amp;rdquo; without a model still needs investigation; wattage cannot tell you build quality.&lt;/p>
&lt;h3 id="marketplace-ambiguity">Marketplace ambiguity&lt;/h3>
&lt;p>The product page must identify seller and fulfillment. It must also state the condition and warranty. The return path needs to be clear. A low price from an unknown seller can erase its savings with one freight return, and on a 40-pound glass-sided tower the expensive failure is rarely the missing five percent of benchmark performance; it is discovering after delivery that the power supply, memory layout, or warranty differs from the product tile while the only remedy is packing the entire machine again.&lt;/p>
&lt;h2 id="the-price-ceiling-for-a-32gb-and-2tb-build">The price ceiling for a 32GB and 2TB build&lt;/h2>
&lt;p>My cutoff for this specification is roughly &lt;strong>$3,500 before tax&lt;/strong>. Cross it, and I want a visible reason:&lt;/p>
&lt;ul>
&lt;li>64GB instead of 32GB&lt;/li>
&lt;li>4TB instead of 2TB&lt;/li>
&lt;li>a premium factory-overclocked RTX 5080&lt;/li>
&lt;li>a clearly better motherboard, PSU, and cooling stack&lt;/li>
&lt;li>a service package worth buying&lt;/li>
&lt;/ul>
&lt;p>A basic 32GB/2TB system at $3,700 is too close to premium-custom pricing. It also gets uncomfortably close to the next GPU tier. If you are willing to assemble the machine, compare the full bill against the &lt;a href="https://techfuelhq.com/pc-builds/2500-dollar-7800x3d-rtx-5080-4k-build-2026/">$2,500-class RTX 5080 build&lt;/a> and load the same parts into the &lt;a href="https://techfuelhq.com/tools/pc-builder/">PC Builder&lt;/a>.&lt;/p>
&lt;h2 id="what-performance-should-you-expect">What performance should you expect?&lt;/h2>
&lt;p>NVIDIA specifies the RTX 5080 with 10,752 CUDA cores, 16GB of GDDR7, a 360W total graphics power rating, and an 850W minimum system requirement. The Ryzen 7 9800X3D supplies eight Zen 5 cores and 96MB of L3 cache on AM5.&lt;/p>
&lt;p>Those specifications put every finalist in the same broad performance class. Cooler design and the installed GPU model decide some of the small gaps, while power limits, BIOS behavior, and memory configuration decide the rest.&lt;/p>
&lt;p>For a measured reference, the &lt;a href="https://techfuelhq.com/gpu-reviews/rog-astral-rtx-5080-oc-review-2026/">ROG Astral RTX 5080 OC review&lt;/a> includes first-party 4K results and a 308-sample power log. The &lt;a href="https://techfuelhq.com/data/gpu/rog-astral-rtx-5080-oc-2026-06-09/">open bench dataset&lt;/a> carries the underlying game and clock rows, plus thermal and power measurements, under CC BY 4.0. Use it as a picture of what one well-cooled premium 5080 did; an OEM card may hold different clocks.&lt;/p>
&lt;p>The practical target is 4K gaming. At 1440p, a cheaper GPU can often deliver the experience without forcing the rest of the build into this price band. The &lt;a href="https://techfuelhq.com/articles/best-gpu-4k-gaming-2026/">2026 4K GPU guide&lt;/a> maps that break point. If your monitor is still 1440p/144Hz, spend against the display before paying for unused GPU headroom.&lt;/p>
&lt;p>Here is the edge case that changes my answer. A buyer who keeps a PC for six years, moves from 1440p to a 4K OLED next spring, runs local models on the 16GB card, and refuses to replace parts mid-cycle can justify buying the 5080 tower before the current monitor demands it. That is a planned multi-use purchase, not a vague future-proofing claim.&lt;/p>
&lt;p>There is measured evidence for the local-model half. On TechFuelHQ&amp;rsquo;s retail RTX 5080, the &lt;a href="https://techfuelhq.com/data/rtx-5080-llm-throughput/">open Ollama throughput dataset&lt;/a> recorded gpt-oss:20b fully GPU-resident at roughly 13.7–14.0 GiB and 187–190 decode tokens per second; the raw CSV is mirrored on Kaggle and Hugging Face. That does not benchmark image generation or prove every 16GB workload fits. It does show that a named local-AI role can be real rather than speculative.&lt;/p>
&lt;p>The six-year plan has named workloads and a named display upgrade, with enough time for the premium to spread across several roles. Remove the 4K display and local workload, and the logic collapses: a gaming-only 1440p buyer is left with expensive capability no current screen or workflow can turn into visible value.&lt;/p>
&lt;h2 id="the-60-second-checkout-audit">The 60-second checkout audit&lt;/h2>
&lt;p>Do this after clicking through and before payment.&lt;/p>
&lt;ol>
&lt;li>Match the item number to the exact row in this guide.&lt;/li>
&lt;li>Confirm Ryzen 7 9800X3D and RTX 5080 16GB in the selected configuration.&lt;/li>
&lt;li>Look for two memory modules. If the page stays silent, ask or check immediately after delivery.&lt;/li>
&lt;li>Confirm the PSU model and a native 12V-2x6 cable where possible.&lt;/li>
&lt;li>Count open M.2 slots and accessible DIMM slots for future upgrades.&lt;/li>
&lt;li>Read who sells it and who ships it.&lt;/li>
&lt;li>Open the warranty and return terms.&lt;/li>
&lt;li>Screenshot the final configuration and delivery promise.&lt;/li>
&lt;/ol>
&lt;p>If one of those fields changes, re-rank the system. The model name on the case matters less than the parts and terms attached to the exact SKU, because two towers wearing the same product-family badge can differ in the power supply and memory layout. They can also arrive with a different motherboard, SSD, cooler, seller, warranty, or delivery promise. Those details decide whether a prebuilt stays an easy purchase or becomes an expensive return. The exact-SKU check is the purchase: without it, a familiar family name can hide a lower-tier power supply, one memory module instead of two, a different motherboard, or a return path that turns a small discount into a freight bill after the tower is already in your house.&lt;/p></description></item><item><title>Best RTX 5090 Prebuilt Gaming PCs (2026)</title><link>https://techfuelhq.com/articles/best-rtx-5090-prebuilt-gaming-pc-2026/</link><pubDate>Tue, 18 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/best-rtx-5090-prebuilt-gaming-pc-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-18 · 14 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="the-three-picks-at-a-glance">The three picks at a glance&lt;/h2>
&lt;p>These systems share the expensive core: Ryzen 7 9800X3D, GeForce RTX 5090 32GB, 32GB DDR5, and 2TB of solid-state storage. The ranking turns on the platform around those parts and the price attached to the exact SKU.&lt;/p>
&lt;p>Same GPU and CPU. Very different risk.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Pick&lt;/th>
&lt;th scope="col">Why it made the list&lt;/th>
&lt;th scope="col">Disclosed power and cooling&lt;/th>
&lt;th scope="col" style="text-align: right">Live Newegg price, Aug. 18&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Stormcraft Valkyrie&lt;/strong>&lt;/td>
&lt;td>Best pick; most complete useful disclosure&lt;/td>
&lt;td>1300W 80 Plus Gold, 360mm AIO&lt;/td>
&lt;td style="text-align: right">&lt;strong>$5,599.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Acer Nitro N80-181-UR19&lt;/strong>&lt;/td>
&lt;td>Best value; same gaming core for $300 less&lt;/td>
&lt;td>1200W, liquid cooling; PSU model not stated&lt;/td>
&lt;td style="text-align: right">&lt;strong>$5,299.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Thermaltake View 9890S&lt;/strong>&lt;/td>
&lt;td>Premium white X870 alternative; not the value choice&lt;/td>
&lt;td>1200W Gold ATX 3.0, Thermaltake 360mm AIO&lt;/td>
&lt;td style="text-align: right">&lt;strong>$6,699.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>All three pages showed &lt;strong>sold and shipped by Newegg&lt;/strong> when captured. These are live-page snapshots. Prices can move. Thermaltake is the important warning: its August 17 affiliate feed showed $6,090.99, but the rendered product page was $6,699.99 on August 18. The checkout page wins that disagreement.&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/best-rtx-5090-prebuilt-gaming-pc-2026.svg" alt="RTX 5090 prebuilt decision diagram showing that every finalist shares the RTX 5090 and Ryzen 7 9800X3D, while the purchase is decided by a native high-current power path, two memory modules, adequate cooling and airflow, and exact seller, warranty, and configuration terms" width="1200" height="630" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="how-i-ranked-the-systems">How I ranked the systems&lt;/h2>
&lt;p>The full August 17 feed held four direct-catalog RTX 5090 desktops. Two Stormcraft rows used the same chassis and price with different processor platforms, so I narrowed the final comparison to the three Ryzen 7 9800X3D systems; holding the gaming CPU, GPU, memory capacity, and storage capacity steady exposes the platform differences instead of burying them under a changing processor.&lt;/p>
&lt;p>I then scored the parts that can turn a $5,000-plus computer into a poor purchase:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Power path.&lt;/strong> NVIDIA rates the RTX 5090 at 575W and specifies 1000W required system power. A 1200W or 1300W supply is the right capacity class here, but capacity is only the start. The model, protections, and native GPU cable still need confirmation.&lt;/li>
&lt;li>&lt;strong>Memory configuration.&lt;/strong> Thirty-two gigabytes must be two modules. Acer and Stormcraft explicitly showed 16GB x 2 in the captured specifications.&lt;/li>
&lt;li>&lt;strong>Cooling and airflow.&lt;/strong> A 360mm AIO earns confidence only as a disclosed component, not as proof of low temperatures or noise. I have not tested these systems.&lt;/li>
&lt;li>&lt;strong>Storage and motherboard.&lt;/strong> A 2TB system drive is the floor. Gen4 detail and a named chipset make future expansion easier to judge.&lt;/li>
&lt;li>&lt;strong>Seller and price integrity.&lt;/strong> The item number, title, live price, seller, and shipper had to agree on the rendered page.&lt;/li>
&lt;/ol>
&lt;p>RGB, &amp;ldquo;AI powered,&amp;rdquo; and giant markdown badges earned nothing. Exact parts and a clean return path did.&lt;/p>
&lt;h2 id="1-stormcraft-valkyrie-is-the-best-pick">1. Stormcraft Valkyrie is the best pick&lt;/h2>
&lt;p>The Valkyrie asks $300 more than Acer and gives a visible reason for most of that difference. Its product page names:&lt;/p>
&lt;ul>
&lt;li>Ryzen 7 9800X3D&lt;/li>
&lt;li>RTX 5090 32GB&lt;/li>
&lt;li>32GB as &lt;strong>two 16GB DDR5-6000 modules&lt;/strong>&lt;/li>
&lt;li>2TB Gen4 NVMe SSD&lt;/li>
&lt;li>AMD B850 motherboard&lt;/li>
&lt;li>360mm AIO liquid cooler&lt;/li>
&lt;li>seven ARGB fans&lt;/li>
&lt;li>1300W 80 Plus Gold power supply&lt;/li>
&lt;/ul>
&lt;p>That is the strongest platform disclosure in the direct-retailer set. The 1300W capacity sits above the practical 1200W target in the &lt;a href="https://techfuelhq.com/articles/what-psu-for-rtx-5080-2026/">RTX 50-series PSU guide&lt;/a>, and the listing gives the memory speed, module count, storage generation, motherboard chipset, radiator size, and fan count. The page also showed Newegg as both seller and shipper.&lt;/p>
&lt;p>Several identities remain hidden: &amp;ldquo;1300W 80 Plus Gold&amp;rdquo; does not name the PSU manufacturer or model, and the listing says component brands may vary, which means the exact graphics card, memory kit, SSD, board model, and supply can change within the stated specification. I cannot call those parts premium. The page still tells the buyer more than the others.&lt;/p>
&lt;p>At $5,599.99, the Valkyrie is the best choice when you want the 5090 tier and would pay $300 to remove several expensive unknowns. Confirm those fields one final time before ordering.&lt;/p>
&lt;h2 id="2-acer-nitro-is-the-value-pick">2. Acer Nitro is the value pick&lt;/h2>
&lt;p>Acer&amp;rsquo;s N80-181-UR19 is the lowest-priced direct 9800X3D and RTX 5090 system in the captured feed and live pages. At $5,299.99, it is $300 below the Stormcraft and $1,400 below the Thermaltake.&lt;/p>
&lt;p>The useful disclosures are better than the short feed title suggests:&lt;/p>
&lt;ul>
&lt;li>Ryzen 7 9800X3D&lt;/li>
&lt;li>RTX 5090 32GB&lt;/li>
&lt;li>32GB DDR5 as &lt;strong>16GB x 2&lt;/strong>&lt;/li>
&lt;li>2TB PCIe SSD&lt;/li>
&lt;li>1200W power supply&lt;/li>
&lt;li>liquid CPU cooling&lt;/li>
&lt;li>Wi-Fi 6 and gigabit Ethernet&lt;/li>
&lt;/ul>
&lt;p>The 1200W capacity is appropriate. The weak point is identity. The page does not name the PSU model or efficiency certification, and its detailed table says only &amp;ldquo;Liquid Cooling&amp;rdquo; even though the title advertises a 240mm AIO. It also leaves the motherboard model and SSD generation unstated.&lt;/p>
&lt;p>That makes Acer the value pick, with a plain trade: save $300 and accept less component identity, or pay Stormcraft for DDR5-6000, a named B850 chipset, Gen4 storage detail, a larger listed radiator, and another 100W of supply capacity. Choose Acer when the support channel, chassis, and saving matter more. Photograph the PSU label and memory modules after delivery, before the return window gets short.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.4458315250198206734392933&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Facer-america-nitro-acer-r7-9800x3d-rtx-5090-32g-32gb-ram-2tb-ssd-liquid-cooling-gaming-pc-win11-geforce-rtx-5090-amd-ryzen-7-9800x3d-32gb-ddr5-2tb-pcie-ssd-n80-181-ur19%2Fp%2FN82E16883101949%3Fitem%3DN82E16883101949"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="3-thermaltake-view-9890s-is-the-premium-alternative">3. Thermaltake View 9890S is the premium alternative&lt;/h2>
&lt;p>The View 9890S has the clearest named cooling and platform combination:&lt;/p>
&lt;ul>
&lt;li>Ryzen 7 9800X3D&lt;/li>
&lt;li>RTX 5090 32GB&lt;/li>
&lt;li>32GB DDR5-6000&lt;/li>
&lt;li>2TB NVMe SSD&lt;/li>
&lt;li>AMD X870 chipset&lt;/li>
&lt;li>Thermaltake 360mm ARGB AIO&lt;/li>
&lt;li>1200W 80 Plus Gold ATX 3.0 power supply&lt;/li>
&lt;li>Wi-Fi 7&lt;/li>
&lt;li>white panoramic chassis&lt;/li>
&lt;/ul>
&lt;p>Those are real differences. X870, a named Thermaltake radiator, Wi-Fi 7, a white build, and a more explicit ATX 3.0 supply description can matter to a buyer who wants this exact design.&lt;/p>
&lt;p>The price breaks the general recommendation: the live page showed $6,699.99, or $1,100 above Stormcraft and $1,400 above Acer, while the prior feed showed $6,090.99. At the live number, the premium buys appearance and platform detail rather than more GPU, CPU, memory, or storage capacity.&lt;/p>
&lt;p>I would skip that premium for gaming performance. This system stays on the list as the distinct white X870 alternative. It does not compete for value at the captured price. If it falls near the Valkyrie, re-run the comparison.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.4458313632340155146618509&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fthermaltake-gaming-desktop-pc-geforce-rtx-5090-amd-ryzen-7-9800x3d-32gb-ddr5-2tb-ssd-lcgs-view-9890s-380xl-white%2Fp%2FN82E16883100115%3Fitem%3DN82E16883100115"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="why-these-are-9800x3d-systems">Why these are 9800X3D systems&lt;/h2>
&lt;p>At this price, the processor should fit the job. The Ryzen 7 9800X3D is an eight-core, 16-thread, 120W AM5 processor with 96MB of L3 cache. It is the gaming-first choice in the captured direct-retailer set.&lt;/p>
&lt;p>The feed also held a $5,599.99 Stormcraft Valkyrie with an Intel Core Ultra 7 270K Plus, a system that can make sense for a different workload mix but would blur this gaming comparison by changing the processor platform while every other finalist stays on the 9800X3D.&lt;/p>
&lt;p>I kept the CPU constant on purpose. Once every row uses a 9800X3D and RTX 5090, the reader can compare the system rather than decoding two product categories at once.&lt;/p>
&lt;h2 id="what-a-5000-plus-prebuilt-must-disclose">What a $5,000-plus prebuilt must disclose&lt;/h2>
&lt;p>The expensive GPU cannot be permission for everything around it to become vague. A machine at this price should make its electrical and upgrade constraints easy to inspect before you pay, then easy to verify again when the box arrives. Two facts from this comparison show why the second check matters. Thermaltake&amp;rsquo;s live price had moved $609 above the prior feed snapshot. Stormcraft warns that component brands may vary inside the stated configuration. Save the checkout screenshot. When the box arrives, compare the delivered graphics card and power supply against the order. Check the memory module count and motherboard next. Finish with the SSD and cooler. Inspect the cabling before the return window gets short.&lt;/p>
&lt;h3 id="a-native-high-current-power-path">A native high-current power path&lt;/h3>
&lt;p>NVIDIA lists 575W total graphics power and 1000W required system power for the RTX 5090. A capacity label of 1200W or 1300W clears the first test. The exact PSU model and a native cable clear the second.&lt;/p>
&lt;p>Avoid treating four adapter leads as a harmless visual issue. This is a high-current connection behind a large card. Confirm the cable type, seat it fully, and avoid a tight bend at the connector.&lt;/p>
&lt;h3 id="two-memory-modules">Two memory modules&lt;/h3>
&lt;p>The captured Acer and Stormcraft pages showed 16GB x 2. Thermaltake disclosed 32GB DDR5-6000 but did not expose the module count in the same table. Confirm two modules before accepting the configuration.&lt;/p>
&lt;p>Thirty-two gigabytes is enough for gaming. The &lt;a href="https://techfuelhq.com/articles/ddr5-ram-buying-guide-2025/">DDR5 buying guide&lt;/a> covers capacity and timing tradeoffs if this tower will also be a 64GB creator or local-AI machine.&lt;/p>
&lt;h3 id="storage-that-fits-the-price">Storage that fits the price&lt;/h3>
&lt;p>Two terabytes is the floor at this tier. Stormcraft identifies its drive as Gen4. Acer says 2TB PCIe, while Thermaltake says 2TB NVMe. None of those capacity lines tells you controller, endurance, or sustained write behavior.&lt;/p>
&lt;p>Identify the installed SSD after delivery and count the open M.2 slots. A $5,500 tower should not require replacing its only system drive just to add working space.&lt;/p>
&lt;h3 id="a-motherboard-and-case-you-can-expand">A motherboard and case you can expand&lt;/h3>
&lt;p>Stormcraft discloses B850. Thermaltake discloses X870. Acer leaves the board unnamed in the saved specification. The chipset will not create gaming frames. It does help define storage lanes and USB. It also tells you more about networking and future cards.&lt;/p>
&lt;p>Case dimensions and slot clearance matter too. An RTX 5090 is not a small component. Confirm that the installed model has room to breathe and that adding another card or bottom-mounted fans will not choke it.&lt;/p>
&lt;h2 id="rtx-5090-or-rtx-5080-prebuilt">RTX 5090 or RTX 5080 prebuilt?&lt;/h2>
&lt;p>The RTX 5090 tier needs a named reason. Mine would be one of these:&lt;/p>
&lt;ul>
&lt;li>maximum native or lightly upscaled 4K performance&lt;/li>
&lt;li>a 4K high-refresh display that can expose the difference&lt;/li>
&lt;li>32GB of VRAM for local AI, rendering, or creation&lt;/li>
&lt;li>one machine serving both gaming and a GPU-heavy paid workload&lt;/li>
&lt;/ul>
&lt;p>If the computer is for ordinary 1440p gaming or 4K with DLSS, the &lt;a href="https://techfuelhq.com/articles/best-rtx-5080-prebuilt-gaming-pc-2026/">best RTX 5080 prebuilt guide&lt;/a> starts at $2,799.99 in the same dated retailer feed. The jump from that value pick to the least expensive 5090 system here was $2,500. That money can buy a serious display and a later GPU upgrade. It can also fund the memory and storage the system will use every day.&lt;/p>
&lt;p>The RTX 5090 is faster. It is not automatically the better purchase. NVIDIA&amp;rsquo;s official specifications put the difference in plain terms: 32GB versus 16GB of GDDR7 and a 575W versus 360W power rating. The &lt;a href="https://techfuelhq.com/articles/best-gpu-4k-gaming-2026/">2026 4K GPU guide&lt;/a> places both cards in the wider buying ladder.&lt;/p>
&lt;h2 id="the-price-ceiling">The price ceiling&lt;/h2>
&lt;p>My practical ceiling for this configuration is about &lt;strong>$6,000 before tax&lt;/strong>. That means a 9800X3D, 32GB, 2TB, and an RTX 5090. Cross the line only when the premium buys something you can name.&lt;/p>
&lt;p>Above that line, I want several of these:&lt;/p>
&lt;ul>
&lt;li>64GB of memory&lt;/li>
&lt;li>4TB or more of quality storage&lt;/li>
&lt;li>an explicitly named premium RTX 5090 model&lt;/li>
&lt;li>a named high-end power supply&lt;/li>
&lt;li>a motherboard and networking stack worth the difference&lt;/li>
&lt;li>a service package with measurable value&lt;/li>
&lt;li>a chassis and cooling configuration you were already willing to buy separately&lt;/li>
&lt;/ul>
&lt;p>Thermaltake&amp;rsquo;s live $6,699.99 can be defended only by the buyer who already values its white panoramic design, X870 platform, Wi-Fi 7, named 360mm cooler, and ATX 3.0 power description. Those features do not make it $1,100 faster than Stormcraft.&lt;/p>
&lt;h2 id="the-60-second-checkout-audit">The 60-second checkout audit&lt;/h2>
&lt;p>Do this after clicking through and before payment.&lt;/p>
&lt;ol>
&lt;li>Match the item number to the exact system in this guide.&lt;/li>
&lt;li>Confirm Ryzen 7 9800X3D, RTX 5090 32GB, 32GB DDR5, and 2TB storage.&lt;/li>
&lt;li>Look for two memory modules and record their speed.&lt;/li>
&lt;li>Identify the exact PSU model and native GPU cable.&lt;/li>
&lt;li>Identify the graphics-card, motherboard, SSD, and cooler models.&lt;/li>
&lt;li>Confirm who sells it and who ships it.&lt;/li>
&lt;li>Open the warranty and return terms, including freight.&lt;/li>
&lt;li>Check case clearance, open M.2 slots, and usable expansion slots.&lt;/li>
&lt;li>Screenshot the final configuration, price, delivery date, and seller block.&lt;/li>
&lt;/ol>
&lt;p>If the configuration changes, the ranking changes with it. At this price, a family name is not a substitute for the exact hardware and terms you are buying.&lt;/p></description></item><item><title>Best Wi-Fi 7 Routers (2026): 3 Picks That Make Sense</title><link>https://techfuelhq.com/networking/best-wifi-7-router-2026/</link><pubDate>Tue, 18 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/networking/best-wifi-7-router-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-18 · 13 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="three-picks-at-a-glance">Three picks at a glance&lt;/h2>
&lt;p>Choose the band layout first. Then count the ports. A giant aggregate speed number comes last because no single client receives the whole number printed on the box.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Pick&lt;/th>
&lt;th scope="col">Best for&lt;/th>
&lt;th scope="col">Radio layout&lt;/th>
&lt;th scope="col">Useful wired I/O&lt;/th>
&lt;th scope="col" style="text-align: right">Live price, Aug. 18&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>TP-Link Archer BE550 Pro&lt;/strong>&lt;/td>
&lt;td>Best for most homes&lt;/td>
&lt;td>Tri-band: 2.4 + 5 + 6GHz&lt;/td>
&lt;td>1× 10G WAN, 4× 2.5G LAN&lt;/td>
&lt;td style="text-align: right">&lt;strong>$229.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ASUS RT-BE88U&lt;/strong>&lt;/td>
&lt;td>Wired-first router and switch replacement&lt;/td>
&lt;td>Dual-band: 2.4 + 5GHz; &lt;strong>no 6GHz&lt;/strong>&lt;/td>
&lt;td>10G SFP+, 10G WAN/LAN, 4× 2.5G, 4× 1G&lt;/td>
&lt;td style="text-align: right">&lt;strong>$338.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ASUS GT-BE98 Pro&lt;/strong>&lt;/td>
&lt;td>Premium wireless capacity and dual-6GHz AiMesh&lt;/td>
&lt;td>Quad-band: 2.4 + 5 + 6 + 6GHz&lt;/td>
&lt;td>10G WAN/LAN, 10G LAN, 3× 2.5G LAN&lt;/td>
&lt;td style="text-align: right">&lt;strong>$629.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>These are dated direct-listing prices. The exact pages resolved and showed the matching product in stock at capture, but the seller and price can move before this article does.&lt;/p>
&lt;img src="https://techfuelhq.com/images/networking/best-wifi-7-router-2026.svg" alt="Wi-Fi 7 router decision map: choose the TP-Link Archer BE550 Pro for tri-band 6GHz value, the ASUS RT-BE88U for dense 10G and 2.5G wired ports despite no 6GHz, or the ASUS GT-BE98 Pro for dual 6GHz radios and flagship wireless capacity" width="1200" height="630" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="the-decision-before-the-product">The decision before the product&lt;/h2>
&lt;p>This page assumes you have already decided Wi-Fi 7 is worth buying. If that question is still open, start with &lt;a href="https://techfuelhq.com/networking/wifi-7-homelab-home-network-2026/">Wi-Fi 7 for the home network and homelab&lt;/a>. It covers real throughput, MLO, client support, and the cases where Wi-Fi 6E should stay in service.&lt;/p>
&lt;p>For the purchase itself, write down four facts:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Does the router need 6GHz?&lt;/strong> If 320MHz channels are part of the plan, yes.&lt;/li>
&lt;li>&lt;strong>What feeds the router?&lt;/strong> Gigabit, 2.5Gbps, 5Gbps, or 10Gbps internet changes the WAN requirement.&lt;/li>
&lt;li>&lt;strong>What sits behind it?&lt;/strong> A NAS, multi-gig switch, or wired gaming PCs decide the LAN ports.&lt;/li>
&lt;li>&lt;strong>Is one access point enough?&lt;/strong> A large or difficult house may need mesh instead of a more expensive standalone box.&lt;/li>
&lt;/ol>
&lt;p>The best router is the least expensive one that serves those four constraints. The rest is unused radio inventory. A flagship only earns its place when the second 6GHz radio, extra 10G path, or denser wired switch replaces another box or fixes a measured bottleneck; without that job, the premium buys capacity that sits idle while the same phone and laptop behave much as they would on the midrange router.&lt;/p>
&lt;h2 id="1-tp-link-archer-be550-pro-is-the-best-pick">1. TP-Link Archer BE550 Pro is the best pick&lt;/h2>
&lt;p>The Archer BE550 Pro is the rare midrange router whose wireless and wired sides match. TP-Link specifies three bands, including 6GHz, with 320MHz channels and MLO. The wired side has one 10Gbps WAN port and four 2.5Gbps LAN ports.&lt;/p>
&lt;p>That combination matters more than the BE9700/BE9300 naming inconsistency between TP-Link and the retailer feed. A fast Wi-Fi client can reach a multi-gig NAS without being pinched through a gigabit LAN port. A 5Gbps fiber service can enter through the 10G WAN port. Four 2.5G LAN ports also remove the immediate need for a small multi-gig switch in many homes.&lt;/p>
&lt;p>At $229.99, it sits where the existing technology guide said useful tri-band Wi-Fi 7 should sit: the low-to-mid $200s. It is $109 below the RT-BE88U and $400 below the GT-BE98 Pro.&lt;/p>
&lt;p>I would still verify three details at checkout. Match &lt;strong>BE550 Pro&lt;/strong>, not the nearby BE550 family name. Confirm the regional version. Then check that the phone, laptop, or desktop you expect to speed up supports 6GHz Wi-Fi 7; a router cannot add a radio to the client.&lt;/p>
&lt;h2 id="2-asus-rt-be88u-is-the-wired-first-exception">2. ASUS RT-BE88U is the wired-first exception&lt;/h2>
&lt;p>The RT-BE88U is an unusual recommendation because its strongest feature is also the reason many Wi-Fi 7 buyers should skip it.&lt;/p>
&lt;p>ASUS calls it dual-band. The official specification and Newegg table show only 2.4GHz and 5GHz wireless. There is no 6GHz radio, so there are no 320MHz 6GHz channels. Put that fact above every marketing number.&lt;/p>
&lt;p>The wired layout is excellent:&lt;/p>
&lt;ul>
&lt;li>one 10G SFP+ port&lt;/li>
&lt;li>one standard 10G WAN/LAN port&lt;/li>
&lt;li>four 2.5G ports&lt;/li>
&lt;li>four gigabit ports&lt;/li>
&lt;li>WAN/LAN aggregation options&lt;/li>
&lt;/ul>
&lt;p>For a homelab or fiber gateway, that can replace both a consumer router and a separate multi-gig switch. The SFP+ port is especially useful when the existing core already speaks DAC or fiber. At $338.99, the additional $109 over TP-Link can be cheaper than buying an extra managed switch.&lt;/p>
&lt;p>For a wireless-first buyer, the logic reverses. Spending more while losing 6GHz makes no sense when the reason for the upgrade is wide-channel Wi-Fi. This is the port-density pick. Nothing else.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.445838548739904449648413&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fasus-rt-be88u-ieee-802-11a-ieee-802-11b-ieee-802-11g-wifi-4-wifi-5-wifi-6-wifi-6e-wifi-7-ipv4-ipv6%2Fp%2FN82E16833320598%3Fitem%3DN82E16833320598"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="3-asus-gt-be98-pro-is-the-flagship">3. ASUS GT-BE98 Pro is the flagship&lt;/h2>
&lt;p>The GT-BE98 Pro carries four radios: 2.4GHz and 5GHz plus two separate 6GHz bands. ASUS pairs that with 320MHz support, one 10G WAN/LAN port, another 10G LAN port, three 2.5G LAN ports, plus AiMesh.&lt;/p>
&lt;p>The second 6GHz radio is the feature that can justify the price. In an AiMesh deployment, one 6GHz band can carry wireless backhaul while the other serves clients. In a dense single-router deployment, the extra radio can divide high-end clients instead of placing them all on one 6GHz channel set.&lt;/p>
&lt;p>Most homes will never turn that capability into a visible result. A single laptop cannot consume four bands. A gigabit internet plan cannot saturate the wired uplink. If the second 6GHz radio has no backhaul or client-density job, the $629.99 price is a $400 premium for idle capacity.&lt;/p>
&lt;p>Buy it for a named topology: dual-6GHz AiMesh, multiple current Wi-Fi 7 clients, 10G core networking, or a flagship gaming network where cost is secondary. The GT-BE98 Pro is the strongest wireless platform here. It is not the default.&lt;/p>
&lt;span class="buy-cell buy-cell--inline">&lt;a class="buy-cell__action buy-cell__action--primary"
href="https://click.linksynergy.com/link?id=CW4UrCo/56I&amp;amp;offerid=1749755.445832470857938676049424&amp;amp;type=15&amp;amp;murl=https%3A%2F%2Fwww.newegg.com%2Fasus-gt-be98-pro%2Fp%2FN82E16833320588%3Fitem%3DN82E16833320588"
rel="nofollow sponsored noopener"
target="_blank"
data-affiliate-retailer="Newegg"
data-affiliate-slot="table-row"
data-link-kind="product">Check Newegg&lt;span class="buy-cell__checked">Link checked 2026-08-18&lt;/span>&lt;/a>&lt;/span>
&lt;h2 id="why-6ghz-changes-the-ranking">Why 6GHz changes the ranking&lt;/h2>
&lt;p>Wi-Fi 7 features are not one indivisible package. MLO and 4K-QAM can operate without 6GHz. The headline 320MHz channels cannot; in the United States they live in the 6GHz band.&lt;/p>
&lt;p>That creates three product classes:&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Class&lt;/th>
&lt;th scope="col">What it gives you&lt;/th>
&lt;th scope="col">What it misses&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Dual-band Wi-Fi 7&lt;/strong>&lt;/td>
&lt;td>MLO/4K-QAM on 2.4 and 5GHz, often strong wired I/O&lt;/td>
&lt;td>6GHz and 320MHz channels&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Tri-band Wi-Fi 7&lt;/strong>&lt;/td>
&lt;td>The full mainstream feature set: 2.4, 5, 6GHz&lt;/td>
&lt;td>A dedicated second 6GHz backhaul/client radio&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Quad-band dual-6GHz&lt;/strong>&lt;/td>
&lt;td>Extra capacity or dedicated 6GHz mesh backhaul&lt;/td>
&lt;td>Value, unless the topology uses it&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>This is why TP-Link wins and ASUS RT-BE88U stays a specialist. The Archer delivers the feature most buyers mean when they say &amp;ldquo;upgrade to Wi-Fi 7.&amp;rdquo; The RT-BE88U delivers a different thing: a serious wired edge with a current-generation 5GHz radio.&lt;/p>
&lt;h2 id="port-topology-beats-a-30gbps-box-number">Port topology beats a 30Gbps box number&lt;/h2>
&lt;p>Router marketing adds every radio&amp;rsquo;s theoretical maximum and prints the sum. That number is access-point capacity under ideal conditions. It is not a laptop speed test.&lt;/p>
&lt;p>Read the physical ports instead:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Archer BE550 Pro:&lt;/strong> cleanest 10G-WAN-to-2.5G-LAN layout.&lt;/li>
&lt;li>&lt;strong>RT-BE88U:&lt;/strong> best wired density and the only SFP+ option here.&lt;/li>
&lt;li>&lt;strong>GT-BE98 Pro:&lt;/strong> two 10G-class paths plus three 2.5G LAN ports.&lt;/li>
&lt;/ul>
&lt;p>For a NAS and workstation, map the whole chain. A 10G router feeding a gigabit switch is still a gigabit network. A Wi-Fi 7 access point wired back through 1GbE is still limited to one gigabit of backhaul. The &lt;a href="https://techfuelhq.com/networking/25gbe-vs-10gbe-homelab-2026/">2.5GbE versus 10GbE guide&lt;/a> explains when the next wired tier pays off.&lt;/p>
&lt;h2 id="standalone-router-or-mesh">Standalone router or mesh?&lt;/h2>
&lt;p>These picks are standalone routers. That is deliberate. A mesh comparison needs node count and backhaul radio first; after that come wired backhaul speed, placement, and total-kit price. Mixing a three-pack Orbi or Deco kit into this table would create the appearance of choice while comparing different products.&lt;/p>
&lt;p>Choose standalone when:&lt;/p>
&lt;ul>
&lt;li>the router can sit near the center of the usable space&lt;/li>
&lt;li>one access point already covers the home&lt;/li>
&lt;li>Ethernet can feed a separate access point later&lt;/li>
&lt;/ul>
&lt;p>Choose mesh when:&lt;/p>
&lt;ul>
&lt;li>floors, dense walls, or distance create repeatable dead zones&lt;/li>
&lt;li>one central location cannot cover the house&lt;/li>
&lt;li>you can wire at least the main satellite with 2.5GbE or faster&lt;/li>
&lt;/ul>
&lt;p>A larger antenna count does not repair a bad access-point location. Spend on topology before flagship hardware. Picture a two-story house with 5Gbps fiber, one wired office, a 10GbE NAS in the basement, and two Wi-Fi 7 laptops upstairs: the Archer serves the wireless upgrade and four 2.5G rooms cleanly; the RT-BE88U earns its premium only if its SFP+ and extra wired ports replace a switch; the GT-BE98 Pro earns its premium only if a second 6GHz radio carries mesh backhaul or a dense client group. The exercise also exposes the mesh question before checkout: if the upstairs devices remain weak because the access point is badly placed, buy a second wired access point or a mesh node rather than paying for a larger standalone router and hoping one box defeats the floor plan.&lt;/p>
&lt;h2 id="do-not-upgrade-to-solve-a-fault">Do not upgrade to solve a fault&lt;/h2>
&lt;p>A router that disconnects clients, reboots, or loses WAN under load may need replacement. It may also have a channel, firmware, heat, power, or ISP problem. Work through &lt;a href="https://techfuelhq.com/articles/wifi-keeps-disconnecting-2026/">Wi-Fi that keeps disconnecting&lt;/a> before using a new wireless generation as a repair strategy.&lt;/p>
&lt;p>The same rule applies to speed. Test a wired client first. If Ethernet is slow, the radio is innocent.&lt;/p>
&lt;h2 id="the-60-second-checkout-audit">The 60-second checkout audit&lt;/h2>
&lt;ol>
&lt;li>Match the exact model and item number.&lt;/li>
&lt;li>Count the bands. Look for 6GHz explicitly.&lt;/li>
&lt;li>Confirm the WAN port speed and whether it can become LAN.&lt;/li>
&lt;li>Count 10G, 2.5G, and 1G LAN ports separately.&lt;/li>
&lt;li>Check whether your clients support Wi-Fi 7 and 6GHz.&lt;/li>
&lt;li>Decide standalone versus mesh before ordering.&lt;/li>
&lt;li>Confirm seller, warranty, return window, and regional version.&lt;/li>
&lt;li>Screenshot the final price and configuration.&lt;/li>
&lt;/ol>
&lt;p>For most buyers, the answer remains the Archer BE550 Pro. It buys the radio that makes Wi-Fi 7 different and the ports that keep it from being trapped behind gigabit.&lt;/p></description></item><item><title>RTX 5090 vs RTX 5080 (2026): Which One Should You Buy?</title><link>https://techfuelhq.com/gpu-reviews/rtx-5090-vs-5080-2026/</link><pubDate>Tue, 18 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/gpu-reviews/rtx-5090-vs-5080-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-18 · 15 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="the-decision-in-one-table">The decision in one table&lt;/h2>
&lt;p>The RTX 5090 wins every absolute-performance question. The RTX 5080 wins the purchase question for most gamers. The exception is a buyer whose current game, render, model, or paid workflow already reaches the 16GB boundary or whose display can turn the 5090&amp;rsquo;s extra native-4K frame rate into something visible; in that case, the larger card solves a named limit rather than serving as expensive insurance.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Decision&lt;/th>
&lt;th scope="col">RTX 5080&lt;/th>
&lt;th scope="col">RTX 5090&lt;/th>
&lt;th scope="col">Winner&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>4K gaming with DLSS&lt;/td>
&lt;td>Strong, measured and playable&lt;/td>
&lt;td>Faster&lt;/td>
&lt;td>&lt;strong>RTX 5080 value&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Maximum native 4K&lt;/td>
&lt;td>Compromises remain in the hardest titles&lt;/td>
&lt;td>Fastest tier&lt;/td>
&lt;td>&lt;strong>RTX 5090&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VRAM&lt;/td>
&lt;td>16GB GDDR7&lt;/td>
&lt;td>32GB GDDR7&lt;/td>
&lt;td>&lt;strong>RTX 5090&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Card power&lt;/td>
&lt;td>360W reference TGP&lt;/td>
&lt;td>575W reference TGP&lt;/td>
&lt;td>&lt;strong>RTX 5080&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Required system power&lt;/td>
&lt;td>850W&lt;/td>
&lt;td>1000W&lt;/td>
&lt;td>&lt;strong>RTX 5080&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Local AI that fits inside 16GB&lt;/td>
&lt;td>Already capable&lt;/td>
&lt;td>Faster/roomier, but unmeasured here&lt;/td>
&lt;td>&lt;strong>RTX 5080 value&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Workloads that exceed 16GB&lt;/td>
&lt;td>Spill or fail&lt;/td>
&lt;td>32GB headroom&lt;/td>
&lt;td>&lt;strong>RTX 5090&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Most gaming builds&lt;/td>
&lt;td>Rational ceiling&lt;/td>
&lt;td>Halo purchase&lt;/td>
&lt;td>&lt;strong>RTX 5080&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;img src="https://techfuelhq.com/images/gpu-reviews/rtx-5090-vs-5080-2026.svg" alt="RTX 5090 versus RTX 5080 decision map: choose the RTX 5080 for most 4K gaming and lower power, or the RTX 5090 when 32GB VRAM, maximum native 4K performance, rendering, or paid GPU work has a defined job" width="1200" height="630" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="current-direct-retailer-example">Current direct-retailer example&lt;/h2>
&lt;p>Launch MSRP is useful history. It is not the number buyers face today.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Exact card&lt;/th>
&lt;th scope="col">What the listing disclosed&lt;/th>
&lt;th scope="col" style="text-align: right">Live price, Aug. 18&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>GIGABYTE WINDFORCE RTX 5080 16GB&lt;/strong>&lt;/td>
&lt;td>304mm long, 2.5 slots, 850W recommended PSU&lt;/td>
&lt;td style="text-align: right">&lt;strong>$1,399.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ASUS ROG Astral RTX 5090 32GB&lt;/strong>&lt;/td>
&lt;td>14.1 inches, 3.8 slots, 1000W recommended PSU&lt;/td>
&lt;td style="text-align: right">&lt;strong>$4,829.99&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>Both pages showed sold and shipped by Newegg at capture. The 5090 example cost &lt;strong>3.45 times&lt;/strong> as much. This is not an apples-to-apples cooler comparison: ROG Astral is a premium flagship board, while WINDFORCE is a simpler RTX 5080. It is still a real checkout comparison, and it shows why MSRP-only advice fails.&lt;/p>
&lt;h2 id="specifications-that-matter">Specifications that matter&lt;/h2>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Specification&lt;/th>
&lt;th scope="col" style="text-align: right">RTX 5080&lt;/th>
&lt;th scope="col" style="text-align: right">RTX 5090&lt;/th>
&lt;th scope="col" style="text-align: right">Difference&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>CUDA cores&lt;/td>
&lt;td style="text-align: right">10,752&lt;/td>
&lt;td style="text-align: right">21,760&lt;/td>
&lt;td style="text-align: right">+11,008&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VRAM&lt;/td>
&lt;td style="text-align: right">16GB GDDR7&lt;/td>
&lt;td style="text-align: right">32GB GDDR7&lt;/td>
&lt;td style="text-align: right">2× capacity&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Memory interface&lt;/td>
&lt;td style="text-align: right">256-bit&lt;/td>
&lt;td style="text-align: right">512-bit&lt;/td>
&lt;td style="text-align: right">2× width&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Total graphics power&lt;/td>
&lt;td style="text-align: right">360W&lt;/td>
&lt;td style="text-align: right">575W&lt;/td>
&lt;td style="text-align: right">+215W&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Required system power&lt;/td>
&lt;td style="text-align: right">850W&lt;/td>
&lt;td style="text-align: right">1000W&lt;/td>
&lt;td style="text-align: right">+150W&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>The core count is not a frame-rate equation. Games do not scale one-for-one with CUDA cores, and CPU limits, memory behavior, ray tracing, and engine design change the gap. The capacity and power differences are literal. They shape what fits in VRAM, which supply belongs in the system, and how much heat the case must move.&lt;/p>
&lt;h2 id="how-much-faster-is-the-rtx-5090">How much faster is the RTX 5090?&lt;/h2>
&lt;p>Two credible suites answer this in different shapes.&lt;/p>
&lt;p>GamersNexus measured the RTX 5090 &lt;strong>30% to 68.9% ahead&lt;/strong> of the RTX 5080 at 4K, depending on the game, with results commonly in the &lt;strong>45% to 55%&lt;/strong> range. That wide spread is the honest result. A single title can land near 30%. Another can approach 70%.&lt;/p>
&lt;p>TechPowerUp&amp;rsquo;s combined 3840×2160 raster chart put the RTX 5090 at &lt;strong>152%&lt;/strong> of the RTX 5080&amp;rsquo;s performance, a 52% suite-level lead. That aligns with the middle of the GamersNexus range while using a different game list and aggregation method.&lt;/p>
&lt;p>The safe buying number is therefore not &amp;ldquo;the 5090 is always 50% faster.&amp;rdquo; It is:&lt;/p>
&lt;ul>
&lt;li>expect a large 4K lead&lt;/li>
&lt;li>expect the exact lead to move by title&lt;/li>
&lt;li>do not pay for the maximum result unless your own games resemble the workloads that produce it&lt;/li>
&lt;/ul>
&lt;p>At 1440p, CPU limits shrink the value of the larger GPU. If the display is 1440p, the RTX 5090 is usually an expensive way to wait on the processor.&lt;/p>
&lt;h2 id="what-the-rtx-5080-already-does-at-4k">What the RTX 5080 already does at 4K&lt;/h2>
&lt;p>TechFuelHQ owns and measures an ASUS ROG Astral RTX 5080 OC. The &lt;a href="https://techfuelhq.com/data/gpu/rog-astral-rtx-5080-oc-2026-06-09/">open bench dataset&lt;/a> publishes raw values with the method and correction history under CC BY 4.0.&lt;/p>
&lt;p>Measured 4K results include:&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Workload&lt;/th>
&lt;th scope="col" style="text-align: right">Average FPS&lt;/th>
&lt;th scope="col" style="text-align: right">1% low&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Cyberpunk 2077 Ultra raster&lt;/td>
&lt;td style="text-align: right">58&lt;/td>
&lt;td style="text-align: right">49&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Cyberpunk RT Ultra, DLSS Quality&lt;/td>
&lt;td style="text-align: right">50&lt;/td>
&lt;td style="text-align: right">41&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Cyberpunk Path Tracing, native&lt;/td>
&lt;td style="text-align: right">19&lt;/td>
&lt;td style="text-align: right">15&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Alan Wake 2 RT, DLSS Quality&lt;/td>
&lt;td style="text-align: right">49&lt;/td>
&lt;td style="text-align: right">38&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Black Myth Wukong Cinematic&lt;/td>
&lt;td style="text-align: right">34&lt;/td>
&lt;td style="text-align: right">27&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>The card needs help in the hardest path-traced workload. That is where DLSS 4 changes the buying decision. On the same system, Cyberpunk 4K path tracing measured:&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Mode&lt;/th>
&lt;th scope="col" style="text-align: right">Output FPS&lt;/th>
&lt;th scope="col" style="text-align: right">PC latency&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Native path tracing&lt;/td>
&lt;td style="text-align: right">19&lt;/td>
&lt;td style="text-align: right">95ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>DLSS Quality, no frame generation&lt;/td>
&lt;td style="text-align: right">40&lt;/td>
&lt;td style="text-align: right">45ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>DLSS Quality + MFG 2×&lt;/td>
&lt;td style="text-align: right">90&lt;/td>
&lt;td style="text-align: right">55ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>DLSS Quality + MFG 4×&lt;/td>
&lt;td style="text-align: right">135&lt;/td>
&lt;td style="text-align: right">62ms&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>If those techniques are acceptable, the RTX 5080 is already a serious 4K card. The RTX 5090 buys more native headroom and a higher starting frame rate. It does not make the RTX 5080 incapable.&lt;/p>
&lt;h2 id="the-16gb-versus-32gb-decision">The 16GB versus 32GB decision&lt;/h2>
&lt;p>For gaming, 16GB is the practical high-end capacity today. The first-party 4K runs above fit and complete on the RTX 5080. Buying 32GB solely because a future game might need it is weak evidence.&lt;/p>
&lt;p>For work, capacity can become binary. A render scene, local model, image batch, or timeline either fits in VRAM or it does not. Once the workload crosses 16GB, the RTX 5090&amp;rsquo;s performance advantage is no longer just frames per second. It can keep work on the GPU that the 5080 must spill, reduce, or refuse.&lt;/p>
&lt;p>Name the workload before paying:&lt;/p>
&lt;ul>
&lt;li>What is the current peak VRAM allocation?&lt;/li>
&lt;li>Does lowering batch size destroy throughput?&lt;/li>
&lt;li>Does CPU/RAM offload create an unacceptable delay?&lt;/li>
&lt;li>Does the extra GPU memory replace a second card, cloud bill, or work interruption?&lt;/li>
&lt;/ul>
&lt;p>If there is no measured 16GB problem, the 32GB answer is insurance at flagship pricing.&lt;/p>
&lt;h2 id="local-ai-use-measured-data-not-parameter-count-folklore">Local AI: use measured data, not parameter-count folklore&lt;/h2>
&lt;p>The &lt;a href="https://techfuelhq.com/data/rtx-5080-llm-throughput/">RTX 5080 local LLM throughput dataset&lt;/a> is measured on the same retail card and mirrored on Kaggle and Hugging Face. It shows what 16GB can already do:&lt;/p>
&lt;ul>
&lt;li>gpt-oss:20b MXFP4: &lt;strong>187–190 decode tokens/second&lt;/strong>&lt;/li>
&lt;li>resident VRAM: roughly &lt;strong>13.7–14.0 GiB&lt;/strong>&lt;/li>
&lt;li>Qwen 2.5 14B Q4_K_M: &lt;strong>94–97 tok/s&lt;/strong>&lt;/li>
&lt;li>Qwen 2.5 7B Q4_K_M: &lt;strong>177–180 tok/s&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>This site has no first-party RTX 5090 AI result, so I will not invent a speed multiplier. The grounded claim is capacity: 32GB gives room for larger fully resident models, longer contexts, image work, plus larger batches. The grounded counterclaim is equally important: 16GB is already enough for fast interactive use on several useful models.&lt;/p>
&lt;p>Buy the 5090 for AI when a workload you run now exceeds the 5080&amp;rsquo;s capacity. Buy the 5080 when your actual models fit.&lt;/p>
&lt;h2 id="power-case-and-the-rest-of-the-system">Power, case, and the rest of the system&lt;/h2>
&lt;p>The RTX 5090 adds 215W of reference board power. That changes more than the electric bill.&lt;/p>
&lt;p>NVIDIA specifies 850W required system power for the RTX 5080 and 1000W for the RTX 5090. TechFuelHQ&amp;rsquo;s &lt;a href="https://techfuelhq.com/articles/what-psu-for-rtx-5080-2026/">full RTX 50-series PSU guide&lt;/a> treats 1200W as the practical high-end 5090 target once a powerful processor and factory-overclocked board enter the build.&lt;/p>
&lt;p>Physical size follows the same pattern in the live examples:&lt;/p>
&lt;ul>
&lt;li>GIGABYTE WINDFORCE RTX 5080: 304mm, 2.5 slots&lt;/li>
&lt;li>ASUS ROG Astral RTX 5090: 14.1 inches, 3.8 slots&lt;/li>
&lt;/ul>
&lt;p>That can determine case choice, front-radiator clearance, lower-slot access, GPU support, and cable bend radius. The GPU price is only the first system cost.&lt;/p>
&lt;h2 id="price-to-performance-without-fake-precision">Price-to-performance without fake precision&lt;/h2>
&lt;p>Using TechPowerUp&amp;rsquo;s 52% combined 4K raster lead and the two live listings above:&lt;/p>
&lt;ul>
&lt;li>performance multiplier: about &lt;strong>1.52×&lt;/strong>&lt;/li>
&lt;li>price multiplier: about &lt;strong>3.45×&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>That does not produce a universal &amp;ldquo;value score.&amp;rdquo; The cards are different AIB tiers, and the RTX 5090 also buys double the VRAM. It does show the shape of the purchase: live retail asks for far more money than the gaming-performance increase alone returns.&lt;/p>
&lt;p>The RTX 5090 can still be the cheaper business tool when its 32GB capacity replaces cloud GPU time, cuts a render queue, or prevents an out-of-memory failure. Put a number on that benefit before paying: if the larger card saves four billable hours each week, avoids a recurring cloud instance, and keeps a current scene fully resident, the purchase has three measurable payback paths; if it only raises a benchmark score, gaming receives none of that accounting benefit.&lt;/p>
&lt;h2 id="buy-the-rtx-5080-if">Buy the RTX 5080 if&lt;/h2>
&lt;ul>
&lt;li>the system is primarily for gaming&lt;/li>
&lt;li>DLSS Quality and frame generation are acceptable at 4K&lt;/li>
&lt;li>current workloads fit inside 16GB&lt;/li>
&lt;li>you want an 850W-class build with easier case fit&lt;/li>
&lt;li>the 5090 price premium would delay the monitor, storage, or next upgrade&lt;/li>
&lt;/ul>
&lt;h2 id="buy-the-rtx-5090-if">Buy the RTX 5090 if&lt;/h2>
&lt;ul>
&lt;li>maximum native or lightly upscaled 4K performance is the requirement&lt;/li>
&lt;li>32GB solves a measured memory-capacity problem&lt;/li>
&lt;li>rendering, AI, or creation time has direct financial value&lt;/li>
&lt;li>the larger PSU, case, cooling, and card price are already budgeted&lt;/li>
&lt;li>money-no-object performance is itself the goal&lt;/li>
&lt;/ul>
&lt;p>The first list describes most buyers. The second describes a smaller group with better reasons, and the difference should survive a simple counterfactual: if the paid workload, 32GB allocation, or native-4K display disappeared tomorrow, would the rest of the purchase still justify a card that costs several thousand dollars more and forces a larger power and cooling envelope?&lt;/p>
&lt;h2 id="complete-system-or-card">Complete system or card?&lt;/h2>
&lt;p>If you want the GPU inside a ready-to-run tower, compare the &lt;a href="https://techfuelhq.com/articles/best-rtx-5080-prebuilt-gaming-pc-2026/">best RTX 5080 prebuilts&lt;/a> and &lt;a href="https://techfuelhq.com/articles/best-rtx-5090-prebuilt-gaming-pc-2026/">best RTX 5090 prebuilts&lt;/a>. Those guides rank power delivery and memory layout, then check storage, seller, and warranty details that disappear when a listing talks only about the GPU.&lt;/p>
&lt;p>For the card alone, confirm the exact item and dimensions, then verify the recommended supply, seller, warranty, and return terms. A GPU family name is not the product in your cart.&lt;/p></description></item><item><title>Monitor Flickering? Use Task Manager to Find the Cause</title><link>https://techfuelhq.com/articles/monitor-flickering-fix-2026/</link><pubDate>Mon, 17 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/monitor-flickering-fix-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published August 17, 2026 · St. Louis, Missouri&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/monitor-flickering-fix-2026.svg" alt="Monitor flickering diagnostic flow: Task Manager separates display-driver flicker from an incompatible app, then the monitor menu separates the PC signal path from the monitor and its power source" width="1200" height="630" loading="eager" fetchpriority="high" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid rgba(200,255,0,0.18);border-radius:8px;" />
&lt;p>A flickering monitor is not one fault. It can be Windows repainting the desktop through a bad driver, one incompatible app flashing while the rest of the display is stable, a video cable losing the signal, an unstable power source, or variable refresh rate making dark scenes pulse.&lt;/p>
&lt;p>That is why the usual list of ten random fixes wastes time. The order matters. I start with &lt;strong>Task Manager&lt;/strong>, because Microsoft&amp;rsquo;s own procedure gives the cleanest Windows-side split: if Task Manager flickers with everything else, the display driver is the likely cause; if Task Manager stays stable while the rest flickers, an app is the likely cause.&lt;/p>
&lt;p>First, name the symptom. A brief loss of the entire picture is a &lt;strong>blackout&lt;/strong>, so use the &lt;a href="https://techfuelhq.com/articles/monitor-keeps-going-black-2026/">monitor-keeps-going-black guide&lt;/a>. A fixed vertical or horizontal band belongs in the &lt;a href="https://techfuelhq.com/articles/lines-on-monitor-screen-2026/">lines-on-monitor guide&lt;/a>. A trail behind motion is &lt;a href="https://techfuelhq.com/articles/how-to-fix-monitor-ghosting-2026/">monitor ghosting&lt;/a>. This page is for the image or brightness visibly pulsing while the picture remains on-screen.&lt;/p>
&lt;p>Do not mix them.&lt;/p>
&lt;h2 id="the-30-second-split">The 30-second split&lt;/h2>
&lt;p>Wait until the flicker is visible, then press &lt;strong>Ctrl + Shift + Esc&lt;/strong> to open Task Manager.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">What flickers?&lt;/th>
&lt;th scope="col">Start here&lt;/th>
&lt;th scope="col">What it rules toward&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Task Manager and the rest of Windows&lt;/td>
&lt;td>Display driver&lt;/td>
&lt;td>Update, roll back, or reinstall the driver&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Everything except Task Manager&lt;/td>
&lt;td>One incompatible app&lt;/td>
&lt;td>Update or uninstall the app that triggers it&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>The monitor&amp;rsquo;s own menu or no-signal box&lt;/td>
&lt;td>Monitor or power source&lt;/td>
&lt;td>Cable-independent panel, board, or outlet problem&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Only a dark game or loading screen with VRR on&lt;/td>
&lt;td>G-Sync / FreeSync / Adaptive Sync&lt;/td>
&lt;td>Frame-time and VRR-range tuning&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Only at a high refresh rate or resolution&lt;/td>
&lt;td>Cable, port, adapter, or bandwidth&lt;/td>
&lt;td>Test a lower rate and a known-good connection&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>Microsoft&amp;rsquo;s &lt;a href="https://support.microsoft.com/en-us/windows/hardware/display-graphics/troubleshoot-screen-flickering-in-windows" rel="noopener">screen-flickering procedure&lt;/a> is explicit. Task Manager flickering with the screen points to the display driver. A stable Task Manager points to an incompatible app. That isolates the Windows side. The monitor still needs its own test.&lt;/p>
&lt;p>One test creates two branches.&lt;/p>
&lt;p>Open the monitor&amp;rsquo;s &lt;strong>on-screen menu&lt;/strong> with its physical button or joystick while the flicker is happening. That menu is drawn by the monitor, not by Windows.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>The menu is stable:&lt;/strong> Samsung&amp;rsquo;s diagnostic boundary points away from monitor service. Keep working the PC, cable, port, and refresh-rate steps below.&lt;/li>
&lt;li>&lt;strong>The menu flickers too:&lt;/strong> disconnect the video cable so the monitor shows its own no-signal message. If that also flickers, the PC is no longer involved. Test the monitor&amp;rsquo;s power source, then the monitor itself.&lt;/li>
&lt;/ul>
&lt;p>Samsung uses the same boundary in its &lt;a href="https://www.samsung.com/us/support/troubleshoot/TSG10007367/" rel="noopener">monitor flicker troubleshooting&lt;/a>. A clean menu or error message means the monitor does not need service; the connected device or cable is causing the issue. Flicker across those internal elements keeps the monitor side under suspicion.&lt;/p>
&lt;h2 id="step-1-reset-the-graphics-driver">Step 1: Reset the graphics driver&lt;/h2>
&lt;p>Press &lt;strong>Windows key + Ctrl + Shift + B&lt;/strong>.&lt;/p>
&lt;p>Windows briefly blanks or redraws the screen while it resets the graphics driver. Microsoft says the shortcut may fix the issue. A stable picture afterward is useful evidence for the Windows display path, but it is not proof that the monitor panel is healthy.&lt;/p>
&lt;p>Do not treat the shortcut as a permanent repair. It restarts the driver; it does not fix why the driver became unstable.&lt;/p>
&lt;p>If the flicker returns:&lt;/p>
&lt;ol>
&lt;li>Open &lt;strong>Device Manager&lt;/strong>.&lt;/li>
&lt;li>Expand &lt;strong>Display adapters&lt;/strong>.&lt;/li>
&lt;li>If the problem started immediately after a driver update, open the adapter&amp;rsquo;s &lt;strong>Properties → Driver&lt;/strong> tab and use &lt;strong>Roll Back Driver&lt;/strong> when available.&lt;/li>
&lt;li>If the driver is old, update it from NVIDIA, AMD, Intel, or the laptop manufacturer.&lt;/li>
&lt;li>If updates and rollback both fail, uninstall the display adapter and let Windows reinstall it, or use the clean-install sequence in the &lt;a href="https://techfuelhq.com/articles/gpu-driver-crash-fix-2026/">GPU driver crash guide&lt;/a>.&lt;/li>
&lt;/ol>
&lt;p>The timing decides whether update or rollback comes first. A driver that started flickering right after an update is not fixed by installing the same update again.&lt;/p>
&lt;h2 id="step-2-if-task-manager-is-stable-find-the-app">Step 2: If Task Manager is stable, find the app&lt;/h2>
&lt;p>When Task Manager stays solid while another window or the rest of the desktop flickers, Microsoft points at an incompatible app.&lt;/p>
&lt;p>Do not reinstall the whole graphics stack yet. Find the smallest repeatable trigger:&lt;/p>
&lt;ul>
&lt;li>Does it begin only when a browser opens?&lt;/li>
&lt;li>Only when Discord, Steam, an overlay, capture software, or a remote-desktop app is visible?&lt;/li>
&lt;li>Only while resizing a specific window?&lt;/li>
&lt;li>Does closing that app stop the flicker immediately?&lt;/li>
&lt;/ul>
&lt;p>Update the app first. If it is already current, uninstall it, restart, and test before reinstalling. That gives you an actual control: same display driver, same monitor, app absent.&lt;/p>
&lt;p>Older or incompatible Windows programs can show flickering windows even when the desktop is otherwise healthy. If one program is the trigger, changing the monitor cable will not repair it.&lt;/p>
&lt;h2 id="step-3-work-the-connection-and-power-path">Step 3: Work the connection and power path&lt;/h2>
&lt;p>Samsung&amp;rsquo;s current monitor guidance puts the practical hardware-side suspects together: a loose or damaged cable, faulty power, high-current appliances on the same circuit, outdated drivers, and the computer&amp;rsquo;s refresh-rate setting.&lt;/p>
&lt;p>Work these in order:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Reseat both ends of the video cable.&lt;/strong> Check for a crushed section, sharp bend, loose latch, or damaged connector.&lt;/li>
&lt;li>&lt;strong>Bypass the extras.&lt;/strong> Remove the dock, KVM, splitter, capture device, and adapter. Connect the PC directly to the monitor.&lt;/li>
&lt;li>&lt;strong>Try another port.&lt;/strong> Move to another output on the graphics card and another input on the monitor.&lt;/li>
&lt;li>&lt;strong>Try a known-good cable.&lt;/strong> Match its certification to the mode you run. The &lt;a href="https://techfuelhq.com/tools/displayport-hdmi-bandwidth-calculator/">DisplayPort and HDMI bandwidth calculator&lt;/a> shows whether the resolution, refresh rate, color depth, and chroma fit the connection.&lt;/li>
&lt;li>&lt;strong>Test another outlet.&lt;/strong> Plug the monitor directly into a different circuit as a control. Keep space heaters and other high-current loads off the same circuit during the test.&lt;/li>
&lt;/ol>
&lt;p>A new cable is evidence only if changing the cable changes the symptom. Buying three cables before running the Task Manager and monitor-menu tests is parts-cannon troubleshooting in a different form.&lt;/p>
&lt;p>Change one thing only.&lt;/p>
&lt;p>The trap is treating every flicker as a cable fault because the cable is visible and easy to replace, when a stable monitor menu, a Task Manager window that flickers with the desktop, and a symptom that began immediately after a driver update together make a far stronger case for the Windows display path than for the wire on your desk.&lt;/p>
&lt;h2 id="step-4-test-the-refresh-rate">Step 4: Test the refresh rate&lt;/h2>
&lt;p>Open &lt;strong>Settings → System → Display → Advanced display&lt;/strong> and confirm Windows is using a refresh rate the monitor supports.&lt;/p>
&lt;p>As a diagnostic, temporarily drop from 144, 165, or 240 Hz to 60 Hz:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Flicker stops at 60 Hz:&lt;/strong> the original display mode is exposing a signal-path or monitor-timing problem. Test the cable, ports, adapters, and native mode separately before naming the failed part.&lt;/li>
&lt;li>&lt;strong>Flicker is unchanged:&lt;/strong> the refresh-rate ceiling was not the cause; return to the driver/app or monitor/power branch.&lt;/li>
&lt;/ul>
&lt;p>Do not leave a high-refresh monitor at 60 Hz. This is a short diagnostic control. Find the weak link, then restore the native rate with the correct cable and port.&lt;/p>
&lt;h2 id="step-5-only-flickers-in-games-test-vrr">Step 5: Only flickers in games? Test VRR&lt;/h2>
&lt;p>If the desktop is stable and the screen pulses in dark game scenes, loading screens, or menus, test &lt;strong>G-Sync, FreeSync, or Adaptive Sync&lt;/strong> before replacing anything.&lt;/p>
&lt;p>Variable refresh rate makes the monitor follow the GPU&amp;rsquo;s frame output. When frame times jump, the refresh rate jumps with them. KTC&amp;rsquo;s &lt;a href="https://us.ktcplay.com/blogs/support-tips/what-causes-monitor-flicker-with-vrr-adaptive-sync" rel="noopener">VRR flicker explanation&lt;/a> describes the repeatable pattern: unstable frame rates force rapid refresh-rate changes, with the effect most visible in dark scenes or near the monitor&amp;rsquo;s VRR floor.&lt;/p>
&lt;p>Run one controlled comparison:&lt;/p>
&lt;ol>
&lt;li>Reproduce the flicker in the same scene.&lt;/li>
&lt;li>Turn G-Sync, FreeSync, or Adaptive Sync off.&lt;/li>
&lt;li>Replay the scene without changing anything else.&lt;/li>
&lt;/ol>
&lt;p>Use the exact same scene.&lt;/p>
&lt;p>If the flicker disappears, the panel is not necessarily dying. Turn VRR back on and cap the frame rate to a level your PC can hold steadily. Also update the GPU driver and monitor firmware. The goal is steadier frame pacing, not a higher peak number.&lt;/p>
&lt;p>Samsung also recommends disabling G-Sync or FreeSync as a flicker test on supported displays.&lt;/p>
&lt;h2 id="step-6-when-the-monitor-itself-becomes-the-likely-fault">Step 6: When the monitor itself becomes the likely fault&lt;/h2>
&lt;p>Only then does the monitor side move to the top.&lt;/p>
&lt;p>Suspect the display or its power board when:&lt;/p>
&lt;ul>
&lt;li>its own on-screen menu flickers;&lt;/li>
&lt;li>its no-signal message flickers with the video cable disconnected;&lt;/li>
&lt;li>the same behavior survives a different cable, input, and source device;&lt;/li>
&lt;li>a different wall outlet and power cord change nothing;&lt;/li>
&lt;li>the flicker appears before Windows loads;&lt;/li>
&lt;li>the panel brightness pulses even while displaying a static internal menu.&lt;/li>
&lt;/ul>
&lt;p>At that point, stop reinstalling drivers. If the monitor is under warranty, record a short video showing the flicker across the on-screen menu and request service. That evidence proves the symptom exists independently of the PC.&lt;/p>
&lt;h2 id="the-fix-order">The fix order&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Separate flicker from a full blackout, fixed line, or motion trail.&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Open Task Manager:&lt;/strong> driver branch if it flickers, app branch if it does not.&lt;/li>
&lt;li>&lt;strong>Open the monitor menu:&lt;/strong> stable means upstream; flickering means monitor or power.&lt;/li>
&lt;li>&lt;strong>Reset the driver&lt;/strong> with Windows key + Ctrl + Shift + B.&lt;/li>
&lt;li>&lt;strong>Reseat and simplify the signal path:&lt;/strong> no dock, KVM, splitter, or adapter.&lt;/li>
&lt;li>&lt;strong>Test another cable, port, and outlet.&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Drop the refresh rate temporarily&lt;/strong> to isolate bandwidth or timing.&lt;/li>
&lt;li>&lt;strong>For game-only flicker, toggle VRR&lt;/strong> and compare the same scene.&lt;/li>
&lt;li>&lt;strong>Request monitor service only after its own menu or no-signal image flickers.&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>That order stays reversible. More importantly, it gives each change a control. Prove which layer is unstable before replacing the layer below it.&lt;/p>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://support.microsoft.com/en-us/windows/hardware/display-graphics/troubleshoot-screen-flickering-in-windows" rel="noopener">Microsoft Support — Troubleshoot screen flickering in Windows&lt;/a> — Task Manager split, graphics-driver reset, driver rollback/update/uninstall, and incompatible-app branch.&lt;/li>
&lt;li>&lt;a href="https://www.samsung.com/us/support/troubleshoot/TSG10007367/" rel="noopener">Samsung Support — Image is distorted, ghosted, or flickering on my Samsung monitor&lt;/a> — cable, power-source, refresh-rate, driver, G-Sync/FreeSync, and monitor-menu controls.&lt;/li>
&lt;li>&lt;a href="https://us.ktcplay.com/blogs/support-tips/what-causes-monitor-flicker-with-vrr-adaptive-sync" rel="noopener">KTC — What causes monitor flicker with VRR or Adaptive Sync&lt;/a> — frame-time swings, rapid refresh-rate changes, dark-scene visibility, and the VRR-floor pattern.&lt;/li>
&lt;/ul></description></item><item><title>Adding a User to the Docker Group Is Not a Convenience Setting (2026)</title><link>https://techfuelhq.com/tutorials/add-user-to-docker-group-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/add-user-to-docker-group-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~8 min read · St. Louis County, MO&lt;/p>
&lt;p>Here is the command you came for:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo groupadd docker &lt;span style="color:#75715e"># only if the group does not exist yet&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo usermod -aG docker $USER
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># then log out and log back in&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And here is the sentence that belongs next to it, which Docker puts in a Warning box on its own post-installation page and almost nobody repeats:&lt;/p>
&lt;blockquote>
&lt;p>The docker group grants root-level privileges to the user.&lt;/p>&lt;/blockquote>
&lt;p>Not &amp;ldquo;elevated access to Docker&amp;rdquo;. Root on the host.&lt;/p>
&lt;h2 id="why-it-is-root-concretely">Why it is root, concretely&lt;/h2>
&lt;p>The reason &lt;code>sudo&lt;/code> is needed in the first place is architectural. Docker&amp;rsquo;s docs put it plainly: the daemon binds a Unix socket rather than a TCP port, that socket is owned by root, and the daemon itself always runs as root. Joining the &lt;code>docker&lt;/code> group does not reduce what the daemon can do. It gives you write access to the socket that commands it.&lt;/p>
&lt;p>The socket is the entire access-control model. Moby&amp;rsquo;s own systemd unit ships it as &lt;code>SocketUser=root&lt;/code>, &lt;code>SocketGroup=docker&lt;/code>, &lt;code>SocketMode=0660&lt;/code>. There is no per-user authorization layer behind it. Anything that can write to that socket can ask the root daemon for anything.&lt;/p>
&lt;p>So the escalation is not clever:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run --mount type&lt;span style="color:#f92672">=&lt;/span>bind,src&lt;span style="color:#f92672">=&lt;/span>/,dst&lt;span style="color:#f92672">=&lt;/span>/host -it alpine sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You are now root inside a container with the host&amp;rsquo;s entire filesystem at &lt;code>/host&lt;/code>. Docker&amp;rsquo;s security page states it directly — the container can alter your host filesystem without any restriction. Edit &lt;code>/host/etc/shadow&lt;/code>, drop a key in &lt;code>/host/root/.ssh/authorized_keys&lt;/code>, whatever you like.&lt;/p>
&lt;p>Notice what is absent. No &lt;code>--privileged&lt;/code>. No sudo prompt. No password. No entry in the sudo log.&lt;/p>
&lt;p>That last one is the part I find most under-discussed. &lt;code>sudo&lt;/code> leaves a trail. Group membership does not.&lt;/p>
&lt;h2 id="so-why-does-every-tutorial-recommend-it">So why does every tutorial recommend it&lt;/h2>
&lt;p>Because Docker&amp;rsquo;s own docs frame it as convenience first. The section opens with the reasoning that if you don&amp;rsquo;t want to preface the docker command with sudo, you create a Unix group called docker and add users to it. The Warning box sits &lt;em>underneath&lt;/em> that.&lt;/p>
&lt;p>Read in order, the page teaches convenience and then qualifies it. Skimmed — which is how anyone with a broken build reads a post-install page — you get the command and miss the box. Docker clearly knows this happens, because they had to add a second and more explicit warning on the Windows side, where &lt;code>docker-users&lt;/code> membership is described as equivalent to granting administrative privileges on the host. OWASP made not exposing the daemon socket rule number one of its Docker cheat sheet.&lt;/p>
&lt;p>The warning exists. It is just positioned to lose.&lt;/p>
&lt;h2 id="why-the-change-does-not-take-effect-immediately">Why the change does not take effect immediately&lt;/h2>
&lt;p>You run &lt;code>usermod&lt;/code>, you run &lt;code>docker ps&lt;/code>, and you still get permission denied. Nothing is broken.&lt;/p>
&lt;p>Supplementary group IDs are a credential attached to a process when it is created. Your shell was created before you joined the group, so it does not carry the membership, and re-reading &lt;code>/etc/group&lt;/code> is not something a running process does. The shell will never pick it up. Neither will your desktop session, or the terminal you opened an hour ago.&lt;/p>
&lt;p>Docker&amp;rsquo;s instruction is to log out and log back in so that group membership is re-evaluated, and they note a Linux VM may need a full restart.&lt;/p>
&lt;p>To test without logging out:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>newgrp docker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run hello-world
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>newgrp&lt;/code> starts a subshell that carries the group. It is a session-level patch. Close that shell and you are back where you started, so do not mistake it for the change having applied globally.&lt;/p>
&lt;h2 id="the-configjson-warning-nobody-explains">The config.json warning nobody explains&lt;/h2>
&lt;p>If you used &lt;code>sudo docker&lt;/code> before joining the group, you will eventually see this:&lt;/p>
&lt;pre tabindex="0">&lt;code>WARNING: Error loading config file: /home/user/.docker/config.json - stat
/home/user/.docker/config.json: permission denied
&lt;/code>&lt;/pre>&lt;p>Root created that directory in your home. Docker documents the fix:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo chown &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$USER&lt;span style="color:#e6db74">&amp;#34;&lt;/span>:&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$USER&lt;span style="color:#e6db74">&amp;#34;&lt;/span> /home/&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$USER&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/.docker -R
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chmod g+rwx &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$HOME&lt;span style="color:#e6db74">/.docker&amp;#34;&lt;/span> -R
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Cosmetic, not dangerous. It will nag until you clear it.&lt;/p>
&lt;h2 id="what-to-do-instead-honestly">What to do instead, honestly&lt;/h2>
&lt;p>I am not going to tell you never to join the docker group. Plenty of people should. The point is to do it knowing what it is.&lt;/p>
&lt;p>&lt;strong>Rootless mode&lt;/strong> is the real fix, because it removes the root daemon rather than gating access to one. It has genuine limitations and I have not run it long enough under a homelab workload to tell you which of those bite in practice, so I will not pretend otherwise.&lt;/p>
&lt;p>&lt;strong>&lt;code>sudo docker&lt;/code>&lt;/strong> keeps every invocation authenticated and logged. It is mildly annoying and it is the correct default on a machine that is not yours alone.&lt;/p>
&lt;p>&lt;strong>Join the group deliberately&lt;/strong> on a box where root-equivalent access is already a thing you accept. On a dedicated homelab Docker host that you administer alone and could rebuild in an afternoon, the trade is reasonable and I would make it.&lt;/p>
&lt;p>What I would not do is join the group on a shared machine, a work laptop, or anything with credentials on it you would not want a container to read, and then tell myself it was a permissions tweak.&lt;/p>
&lt;p>The same reasoning governs anything you point at that socket. A &lt;a href="https://techfuelhq.com/tutorials/dockge-docker-compose-manager-2026/">Dockge&lt;/a> or Portainer container with the socket mounted is not a dashboard; it is that same root-equivalent access with a web login in front of it.&lt;/p>
&lt;h2 id="the-docker-desktop-exception">The Docker Desktop exception&lt;/h2>
&lt;p>This is the one place the warning genuinely does not carry over. On Docker Desktop the daemon and your containers run inside a Linux VM, and Docker documents that VM as the security boundary. Container root is not host root in the way it is on a native Linux install.&lt;/p>
&lt;p>Do not port the Linux Engine threat model onto Desktop unexamined. Do not port Desktop&amp;rsquo;s comfort back onto a Linux server either — on Windows, &lt;code>docker-users&lt;/code> carries its own warning, in Docker&amp;rsquo;s words equivalent to granting administrative privileges on the host.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run rootless mode as a daily driver, so I cannot tell you where its limitations actually hurt versus where they are theoretical.&lt;/p>
&lt;p>I have not audited whether any mainstream distro ships auditd rules that would record socket writes by group members. My claim above is that &lt;code>sudo&lt;/code> logs and group membership does not, which follows from how each works, but I have not sat down and confirmed what a default install captures.&lt;/p>
&lt;h2 id="what-getting-this-wrong-costs">What getting this wrong costs&lt;/h2>
&lt;p>On your own homelab box, usually nothing. That is exactly why the habit spreads.&lt;/p>
&lt;p>The bill arrives somewhere else. It arrives when the same muscle memory runs &lt;code>usermod -aG docker&lt;/code> on a shared build server, and the service account that now has passwordless unlogged root is the one whose CI token leaks six months later. Nobody has to attack Docker. The group was the grant.&lt;/p>
&lt;p>Run the command if it suits your machine. Just do not believe it only saves you four keystrokes.&lt;/p></description></item><item><title>Docker Cleanup: Which Prune Command Eats Your Data (2026)</title><link>https://techfuelhq.com/tutorials/docker-cleanup-disk-space-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/docker-cleanup-disk-space-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~8 min read · St. Louis County, MO&lt;/p>
&lt;p>The received wisdom is simple. &lt;code>docker system prune -a --volumes&lt;/code> eats databases, so never run it.&lt;/p>
&lt;p>That fear is aimed at the wrong command. Docker&amp;rsquo;s own options table describes &lt;code>--volumes&lt;/code> as &lt;strong>&amp;ldquo;Prune anonymous volumes&amp;rdquo;&lt;/strong>, and the confirmation prompt spells out what it will remove: all anonymous volumes not used by at least one container. A named volume is not anonymous. If your Postgres data lives in a volume you named in a compose file, &lt;code>docker system prune -a --volumes&lt;/code> is not the thing that will take it.&lt;/p>
&lt;p>The command that removes named volumes is this one.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker volume prune --all
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Docker documents that by default &lt;code>docker volume prune&lt;/code> only removes anonymous volumes, and that &lt;code>--all&lt;/code> removes all unused volumes, not just anonymous ones, behind an API 1.42 gate. Read those two sentences next to each other and the asymmetry is obvious: the destructive option is a four-character flag on a command whose name sounds like it only touches leftovers.&lt;/p>
&lt;p>So the scary-sounding command is narrower than its reputation. The mild-sounding one is the loaded gun. That inversion — feared command safe, safe-sounding command dangerous — is the whole reason this page exists.&lt;/p>
&lt;p>One honest caveat before you act on any of it. Everything above is read from Docker&amp;rsquo;s current documentation, not from a test I ran on this machine. I have no Docker daemon here, and I would rather say so than imply a bench I did not use. There is a two-minute scratch test at the end. Run it first. Trust it over me.&lt;/p>
&lt;h2 id="look-before-you-sweep">Look before you sweep&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker system df
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That breaks usage into images, containers, local volumes and build cache, with a reclaimable column. Run it first. Every time.&lt;/p>
&lt;p>I push this because &amp;ldquo;reclaim disk space&amp;rdquo; is usually the wrong framing, and running a prune before you have looked at &lt;code>docker system df&lt;/code> is how people end up re-pulling forty gigabytes of images to solve a problem that was one container writing an unbounded log file the whole time. The question is what filled the disk, and the answer changes the fix entirely. Build cache on a machine that builds often is a different problem from forty pulled images you never run, which is different again from one container writing an unbounded log. Only one of those is solved by pruning.&lt;/p>
&lt;h2 id="what-each-command-removes">What each command removes&lt;/h2>
&lt;p>&lt;strong>&lt;code>docker system prune&lt;/code>&lt;/strong>, per its confirmation prompt, removes exactly four things:&lt;/p>
&lt;ul>
&lt;li>all stopped containers&lt;/li>
&lt;li>all networks not used by at least one container&lt;/li>
&lt;li>all dangling images&lt;/li>
&lt;li>unused build cache&lt;/li>
&lt;/ul>
&lt;p>No volumes at all. A dangling image — one that no tag points at any more — is typically what is left after rebuilding under the same tag.&lt;/p>
&lt;p>&lt;strong>&lt;code>docker system prune -a&lt;/code>&lt;/strong> adds, per the options table: &lt;em>Remove all unused images not just dangling ones&lt;/em>.&lt;/p>
&lt;p>This is a much wider sweep than it reads. &amp;ldquo;Unused&amp;rdquo; means no container is associated with the image, tagged or not. On a homelab where you keep images around for things you run occasionally, &lt;code>-a&lt;/code> removes them and you will pull them again over your home connection at the least convenient moment. It is safe for your data. It is expensive for your time.&lt;/p>
&lt;p>&lt;strong>&lt;code>docker system prune --volumes&lt;/code>&lt;/strong> adds anonymous volumes, as covered above.&lt;/p>
&lt;p>&lt;strong>&lt;code>docker volume prune&lt;/code>&lt;/strong> takes anonymous volumes only, by default.&lt;/p>
&lt;p>&lt;strong>&lt;code>docker volume prune --all&lt;/code>&lt;/strong> is the one to watch. Unused named volumes go too.&lt;/p>
&lt;p>&lt;strong>&lt;code>docker builder prune&lt;/code>&lt;/strong> takes build cache only. It is the safest command here, because build cache is reproducible by definition. On a machine that builds regularly it is also often the entire problem.&lt;/p>
&lt;h2 id="the-trap-that-is-genuinely-real">The trap that is genuinely real&lt;/h2>
&lt;p>Here is the case where you can genuinely lose data to anonymous-volume pruning. It is not the one people worry about.&lt;/p>
&lt;p>Some official images declare a &lt;code>VOLUME&lt;/code> in their Dockerfile. Postgres declares one at its data directory. When you start such an image without giving it a named volume or a bind mount, Docker satisfies that declaration by creating an anonymous volume. It has a long hex name you never chose. It holds your actual database.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># creates an anonymous volume holding real data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run -d postgres:17
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># creates a named volume you control&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run -d -v pgdata:/var/lib/postgresql/data postgres:17
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Stop that first container and the anonymous volume is now unused, and squarely in scope for &lt;code>--volumes&lt;/code>.&lt;/p>
&lt;p>So the failure mode is not &amp;ldquo;prune ate my named volume&amp;rdquo;. It is &amp;ldquo;I never named the volume, so Docker quietly named it for me, that autogenerated name made it anonymous by definition, and anonymous is precisely the category the flag I ran was documented to remove&amp;rdquo;. The fix is upstream of any prune command: name your volumes. A compose file with a top-level &lt;code>volumes:&lt;/code> block gets this right by default, which is one more reason to run things through compose rather than long &lt;code>docker run&lt;/code> lines.&lt;/p>
&lt;h2 id="what-i-run-weekly">What I run weekly&lt;/h2>
&lt;p>Weekly, on a homelab Docker host, with the reasoning attached:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker system df &lt;span style="color:#75715e"># look first&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker builder prune &lt;span style="color:#75715e"># cache is reproducible&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker system prune &lt;span style="color:#75715e"># stopped containers, unused networks, dangling images&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That reclaims most of what accumulates. It touches nothing you cannot rebuild.&lt;/p>
&lt;p>I add &lt;code>-a&lt;/code> only when I have decided I am willing to re-pull, which on a metered or slow connection is a real cost rather than a theoretical one.&lt;/p>
&lt;p>I never run &lt;code>docker volume prune --all&lt;/code> on a schedule. A volume is the one thing here that might be the only copy. When I want a specific volume gone, I look at it first and then remove it by name, which is slower in exactly the way that a command capable of destroying the only copy of something ought to be:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker volume ls
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker volume inspect &amp;lt;name&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker volume rm &amp;lt;name&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Slower. It also makes me say what I mean.&lt;/p>
&lt;h2 id="the-scratch-test-so-you-do-not-have-to-take-my-word-for-it">The scratch test, so you do not have to take my word for it&lt;/h2>
&lt;p>Two minutes, on a machine where losing the test volumes costs nothing.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker volume create keepme
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run -d --name anon-test postgres:17 &lt;span style="color:#75715e"># anonymous volume&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run -d --name named-test -v keepme:/data alpine sleep &lt;span style="color:#ae81ff">60&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker rm -f anon-test named-test
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker volume ls &lt;span style="color:#75715e"># note what exists&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker system prune -a --volumes &lt;span style="color:#75715e"># the feared command&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker volume ls &lt;span style="color:#75715e"># keepme should still be here&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If &lt;code>keepme&lt;/code> survives and the hex-named one does not, the documented behaviour holds on your version. If it does not survive, I want to know — that would mean the docs and your daemon disagree, which is a much more interesting problem than a tidy disk.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run any of this on a live daemon during this write-up, for the reason given at the top. Every behavioural claim here traces to Docker&amp;rsquo;s current CLI documentation.&lt;/p>
&lt;p>I have not checked how an older daemon behaves, and this is the gap I would most want closed before anyone runs these commands on a long-lived box that has not been updated in a couple of years. &lt;code>--all&lt;/code> on &lt;code>docker volume prune&lt;/code> carries an API 1.42 gate, which implies the pre-1.42 behaviour differed, and I have not established what a new CLI does against an old daemon. If you are on something long-lived and unpatched, test rather than assume.&lt;/p>
&lt;p>I have not measured how much any of this reclaims in practice. That number is a property of your machine, and quoting mine would tell you nothing.&lt;/p>
&lt;h2 id="what-getting-it-wrong-costs">What getting it wrong costs&lt;/h2>
&lt;p>Pruning images costs you a download. Pruning build cache costs one slow build. Both are annoyances with a known price.&lt;/p>
&lt;p>Pruning a volume costs you whatever was in it, and the price is only discovered later, usually when something tries to read data that is no longer there and fails in a way that does not obviously say &amp;ldquo;your volume is gone&amp;rdquo;. If that data mattered, the real lesson is not about prune flags at all. It is that a volume you would miss should be &lt;a href="https://techfuelhq.com/homelab/restic-vs-borg-vs-kopia-2026/">backed up&lt;/a>, because a wrong flag is only one of many ways to lose it.&lt;/p></description></item><item><title>Docker Compose Environment Variables: .env Is Not env_file (2026)</title><link>https://techfuelhq.com/tutorials/docker-compose-environment-variables-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/docker-compose-environment-variables-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~9 min read · St. Louis County, MO&lt;/p>
&lt;p>Put a &lt;code>.env&lt;/code> file next to your &lt;code>compose.yaml&lt;/code>, fill it with variables, start the stack, and exec into the container to check.&lt;/p>
&lt;p>They are not there.&lt;/p>
&lt;p>This is the single most common Compose confusion. It is also not carelessness.&lt;/p>
&lt;p>The two mechanisms have similar names, similar syntax, and point in opposite directions.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>.env&lt;/code>&lt;/strong> fills &lt;code>${VAR}&lt;/code> placeholders &lt;strong>in the compose file itself&lt;/strong>. By itself it puts nothing in a container.&lt;/li>
&lt;li>&lt;strong>&lt;code>env_file:&lt;/code>&lt;/strong> passes variables &lt;strong>into the container&lt;/strong>, and is not consulted when Compose interpolates the compose file.&lt;/li>
&lt;/ul>
&lt;p>Docker says the first half plainly. Their precedence page notes that the Host OS environment and &lt;code>.env&lt;/code> file columns are listed only for illustration purposes, and that in reality they do not result in a variable in the container by itself.&lt;/p>
&lt;p>Read that twice. It is the whole article.&lt;/p>
&lt;h2 id="the-two-directions-side-by-side">The two directions, side by side&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># .env (interpolation source)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">POSTGRES_VERSION=17&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># compose.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">db&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">postgres:${POSTGRES_VERSION} &lt;/span> &lt;span style="color:#75715e"># .env fills THIS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">env_file&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">db.env &lt;/span> &lt;span style="color:#75715e"># this goes INTO the container&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">TZ=America/Chicago &lt;/span> &lt;span style="color:#75715e"># so does this&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>POSTGRES_VERSION&lt;/code> never reaches the container.&lt;/p>
&lt;p>&lt;code>TZ&lt;/code> and everything in &lt;code>db.env&lt;/code> do reach it, and neither of them can interpolate anything, which means the file you edited and the file you needed to edit are frequently different files.&lt;/p>
&lt;p>The mirror-image mistake is just as common and harder to spot:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">web&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;webapp:${TAG}&amp;#34;&lt;/span> &lt;span style="color:#75715e"># TAG will NOT come from env_file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">env_file&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">.env&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Listing &lt;code>.env&lt;/code> under &lt;code>env_file:&lt;/code> does not make its contents available for interpolation. It makes them available inside the container, which is a different thing that you did not ask for.&lt;/p>
&lt;h2 id="precedence-in-the-order-docker-documents">Precedence, in the order Docker documents&lt;/h2>
&lt;p>Highest to lowest, for what ends up in the container:&lt;/p>
&lt;ol>
&lt;li>&lt;code>docker compose run -e&lt;/code> on the CLI&lt;/li>
&lt;li>&lt;code>environment&lt;/code> or &lt;code>env_file&lt;/code> &lt;strong>with no value&lt;/strong> — passes through from your shell&lt;/li>
&lt;li>the &lt;code>environment&lt;/code> attribute&lt;/li>
&lt;li>the &lt;code>env_file&lt;/code> attribute&lt;/li>
&lt;li>a Dockerfile &lt;code>ARG&lt;/code> or &lt;code>ENV&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>Two entries in that list catch people.&lt;/p>
&lt;p>&lt;strong>&lt;code>environment&lt;/code> beats &lt;code>env_file&lt;/code>, even when it is empty.&lt;/strong> Docker&amp;rsquo;s wording is explicit that this holds true even if those values are empty or undefined. So a leftover &lt;code>FOO=&lt;/code> under &lt;code>environment:&lt;/code> silently overrides a correct &lt;code>FOO&lt;/code> in your env file. Nothing warns you. The variable is simply empty, and you spend the next twenty minutes reading the env file, which is correct, because the problem is in the other file entirely.&lt;/p>
&lt;p>&lt;strong>A Dockerfile default is a fallback.&lt;/strong> The docs state that having any &lt;code>ARG&lt;/code> or &lt;code>ENV&lt;/code> setting in a Dockerfile evaluates only if there is no Compose entry for &lt;code>environment&lt;/code>, &lt;code>env_file&lt;/code> or &lt;code>run --env&lt;/code>. You do not layer on top of it. You replace it entirely.&lt;/p>
&lt;p>There is also a second, &lt;em>different&lt;/em> precedence list in the docs covering interpolation: shell, then &lt;code>--env-file&lt;/code>, then the project &lt;code>.env&lt;/code>. Two lists. Two jobs. Reading one and applying it to the other is how people end up certain the docs contradict themselves.&lt;/p>
&lt;h2 id="the-silent-failures">The silent failures&lt;/h2>
&lt;p>This is what makes the topic worth a page rather than a paragraph.&lt;/p>
&lt;p>Almost every way to get it wrong fails quietly.&lt;/p>
&lt;p>&lt;strong>Unset interpolated variables become empty strings, not errors.&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;postgres:${POSTGRES_VERSION}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>With &lt;code>POSTGRES_VERSION&lt;/code> unset, that resolves to &lt;code>postgres:&lt;/code>, which the docs note is not a valid image reference.&lt;/p>
&lt;p>Compose builds the string anyway and hands you the failure one layer down, where the error message talks about an image rather than about the variable that produced it, so the search you run next is the wrong search.&lt;/p>
&lt;p>&lt;strong>Bare passthrough does not warn; the explicit form does.&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">DEBUG &lt;/span> &lt;span style="color:#75715e"># unset? no warning, nothing passed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">DEBUG=${DEBUG} &lt;/span> &lt;span style="color:#75715e"># unset? Compose warns&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Both are legal. Only the second tells you when the shell had nothing to give. I use it for that reason alone.&lt;/p>
&lt;p>&lt;strong>A missing &lt;code>--env-file&lt;/code> is a hard error. A missing &lt;code>.env&lt;/code> is silent.&lt;/strong>&lt;/p>
&lt;p>That asymmetry is deliberate. A path you named explicitly is a promise; the default is optional. It also means a stack that runs on your laptop can start on the server with a chunk of its configuration quietly absent, because &lt;code>.env&lt;/code> was never committed and nobody noticed it was gone.&lt;/p>
&lt;p>I check for that first now, whenever something runs locally and not on the host. It is nearly always this.&lt;/p>
&lt;h2 id="secrets-do-not-belong-here">Secrets do not belong here&lt;/h2>
&lt;p>Anything you put in the container environment is readable with &lt;code>docker inspect&lt;/code>. That means it is readable by anyone who can reach the Docker socket — and on a Linux host, &lt;a href="https://techfuelhq.com/tutorials/add-user-to-docker-group-2026/">that is anyone in the docker group&lt;/a>, which is root-equivalent access anyway.&lt;/p>
&lt;p>Compose supports file-based secrets that arrive at &lt;code>/run/secrets/&amp;lt;name&amp;gt;&lt;/code> instead:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">db&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">postgres:17&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">POSTGRES_PASSWORD_FILE&lt;/span>: &lt;span style="color:#ae81ff">/run/secrets/db_password&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">secrets&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">db_password&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">secrets&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">db_password&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">file&lt;/span>: &lt;span style="color:#ae81ff">./db_password.txt&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note the pattern in that block. The environment variable holds a path. The secret itself never enters the environment. Many official images support a &lt;code>_FILE&lt;/code> suffix on their password variables for exactly this, and where an image supports it, it is strictly better than pasting the value.&lt;/p>
&lt;p>&lt;code>ARG&lt;/code> deserves a specific warning too: build arguments are visible in the image history. An &lt;code>ARG&lt;/code> carrying a token is published rather than private, and it stays published in every layer built from it.&lt;/p>
&lt;h2 id="what-i-do">What I do&lt;/h2>
&lt;p>A &lt;code>.env&lt;/code> for things that shape the compose file: versions, ports, host paths.&lt;/p>
&lt;p>An &lt;code>env_file&lt;/code> per service for what the application reads.&lt;/p>
&lt;p>&lt;code>environment&lt;/code> for one or two values I want visible in the compose file itself, so that reading the file tells the truth about what the service gets rather than sending the reader off to a second file to find out.&lt;/p>
&lt;p>The rule I hold to, after being bitten by the empty-override: &lt;strong>never set the same variable in two places.&lt;/strong> Precedence rules exist so that Compose can resolve a conflict, not so that I can create one and rely on remembering the order at 1am.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not verified the behaviour on old Compose v1. Everything here is from current Compose documentation, and v1 differed in enough places that I would not extend it there.&lt;/p>
&lt;p>I have not tested how the newer top-level &lt;code>include:&lt;/code> interacts with &lt;code>.env&lt;/code> resolution across multiple compose files, which is the case I would most expect to hold a surprise.&lt;/p>
&lt;h2 id="what-getting-it-wrong-costs">What getting it wrong costs&lt;/h2>
&lt;p>Usually an hour. The hour has a distinctive shape: the configuration looks correct, the container disagrees, and nothing produces an error that points at either one.&lt;/p>
&lt;p>Occasionally it costs more. &lt;code>environment&lt;/code> silently overriding an env-file value with an empty string is a fine way to start a database with an empty password variable, and the failure mode there depends entirely on how forgiving the image is about it. Some are not forgiving at all, which is the good outcome.&lt;/p></description></item><item><title>Dockge Setup: The Compose Manager That Does Less On Purpose (2026)</title><link>https://techfuelhq.com/tutorials/dockge-docker-compose-manager-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/dockge-docker-compose-manager-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~7 min read · St. Louis County, MO&lt;/p>
&lt;p>Dockge is a web UI over a folder of &lt;code>docker-compose.yaml&lt;/code> files. That sentence is the entire product. I mean it as praise.&lt;/p>
&lt;p>The install is one container. Five minutes, most of it waiting on a pull. The thing worth reading this page for is the volume line in the middle of that file, because getting it wrong is the one failure the project cared enough about to put a warning emoji beside in its own README, and because it fails quietly rather than loudly.&lt;/p>
&lt;h2 id="the-compose-file">The compose file&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dockge&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">louislam/dockge:1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">5001&lt;/span>:&lt;span style="color:#ae81ff">5001&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/var/run/docker.sock:/var/run/docker.sock&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./data:/app/data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Both sides of this MUST be the same path. See below.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/opt/stacks:/opt/stacks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">DOCKGE_STACKS_DIR=/opt/stacks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">PUID=1000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">PGID=1000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>mkdir -p /opt/dockge /opt/stacks &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> cd /opt/dockge
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># save the file above as compose.yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker compose up -d
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then open port 5001 and create the admin account. Done.&lt;/p>
&lt;h2 id="before-you-run-that-the-stable-image-is-old">Before you run that: the stable image is old&lt;/h2>
&lt;p>I nearly published this page without checking. That would have been a disservice, so here it is up front, ahead of the install advice rather than buried in a caveats section at the bottom where nobody reads it.&lt;/p>
&lt;p>Dockge 1.5.0 was released on &lt;strong>30 March 2025&lt;/strong>. On Docker Hub the tags &lt;code>1&lt;/code>, &lt;code>latest&lt;/code> and &lt;code>1.5.0&lt;/code> all resolve to one digest, and all three were last pushed that same day. The &lt;code>1&lt;/code> tag in the compose file above is therefore an image that has not been rebuilt in roughly sixteen months.&lt;/p>
&lt;p>The project is not abandoned. Master took commits into April 2026, and there is a &lt;code>nightly&lt;/code> tag rebuilt daily from it, which I confirmed had been pushed the day I wrote this. What has stalled is the &lt;em>release&lt;/em>. The gap between the code and the artefact you actually pull is the part that matters, and it is the part a version number on a README will never show you.&lt;/p>
&lt;p>Now weigh that against the socket mount in the next section. This is a container holding root-equivalent access to your host, running an image whose base layers have not been refreshed in over a year. Those two facts are worse together than either is alone.&lt;/p>
&lt;p>I still think it is worth running. On a LAN-only host, behind a proxy, on a homelab you could rebuild in an afternoon. I would not put it on anything internet-facing, and I would not put it on a machine whose loss would ruin a week. You can pin &lt;code>nightly&lt;/code> for the newer code. Then you are on unreviewed daily builds, which is a different risk, not a smaller one.&lt;/p>
&lt;p>Check the dates yourself before installing. They may well have moved since I wrote this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -s &lt;span style="color:#e6db74">&amp;#34;https://hub.docker.com/v2/repositories/louislam/dockge/tags?page_size=10&amp;amp;ordering=last_updated&amp;#34;&lt;/span> | python -c &lt;span style="color:#e6db74">&amp;#34;import json,sys; [print(t[&amp;#39;name&amp;#39;], t[&amp;#39;last_updated&amp;#39;][:10]) for t in json.load(sys.stdin)[&amp;#39;results&amp;#39;]]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="the-volume-line">The volume line&lt;/h2>
&lt;p>Look at the stacks mount again:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ae81ff">/opt/stacks:/opt/stacks&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Host path on the left, container path on the right. They are identical, and that is not stylistic. The README&amp;rsquo;s own examples are blunt about it — it marks &lt;code>/my-stacks:/my-stacks&lt;/code> correct because both paths match, and &lt;code>/docker:/my-stacks&lt;/code> wrong because they do not, with the warning that your data could end up written into a wrong path.&lt;/p>
&lt;p>Here is why. &amp;ldquo;Just do it&amp;rdquo; is unsatisfying, and you will meet this shape again.&lt;/p>
&lt;p>Dockge talks to the Docker daemon through the socket you mounted. When it asks the daemon to bring up a stack, the daemon resolves every path in that compose file &lt;strong>on the host&lt;/strong>, not inside the Dockge container. So Dockge writes a compose file to what it believes is &lt;code>/opt/stacks/immich/compose.yaml&lt;/code>, and the daemon goes looking for that same path on the host. If your bind was &lt;code>/docker:/opt/stacks&lt;/code>, then Dockge&amp;rsquo;s &lt;code>/opt/stacks/immich&lt;/code> is really &lt;code>/docker/immich&lt;/code> on the host, and the two halves of the system now disagree about where your stacks live.&lt;/p>
&lt;p>Make both sides identical and the disagreement cannot happen. It is the same class of problem as any socket-mounted tool that hands paths to the daemon, and the fix is always the same: agree with the host.&lt;/p>
&lt;p>&lt;code>/opt/stacks&lt;/code> is only a convention, and &lt;code>/srv/stacks:/srv/stacks&lt;/code> would do just as well, because what the daemon cares about is that the two sides agree rather than what they agree on. Matching is the rule. The path is yours.&lt;/p>
&lt;h2 id="what-it-deliberately-will-not-do">What it deliberately will not do&lt;/h2>
&lt;p>Dockge is compose-only. It will not manage standalone containers, networks, images, or the rest of the Docker surface Portainer covers.&lt;/p>
&lt;p>I think that is the most interesting thing about it. It is also the part people get annoyed by, because they arrive expecting a Portainer swap and find something with a deliberately smaller footprint instead. If every workload you run is a compose stack — which, in a homelab, it usually is — then a tool that only does stacks has a much smaller surface to be confusing in. If you regularly poke at networks or one-off containers, Dockge will not cover that and you will keep a terminal open. Neither of those is a defect. They are just different jobs.&lt;/p>
&lt;p>I compare it properly against the two obvious alternatives in &lt;a href="https://techfuelhq.com/homelab/komodo-vs-portainer-vs-dockge-2026/">Komodo vs Portainer vs Dockge&lt;/a>, including the licensing change that pushed a lot of people to look in the first place.&lt;/p>
&lt;h2 id="security-briefly-because-the-socket-mount-deserves-it">Security, briefly, because the socket mount deserves it&lt;/h2>
&lt;p>That first volume line mounts the Docker socket into the container. Anything that can reach the Docker socket can start a container that mounts your host filesystem as root. That is not a partial privilege. It is root.&lt;/p>
&lt;p>So the Dockge UI is not a dashboard. It is a root-equivalent control surface with a login form in front of it. Treat it that way:&lt;/p>
&lt;ul>
&lt;li>Do not publish 5001 to the internet. Put it behind &lt;a href="https://techfuelhq.com/tutorials/nginx-proxy-manager-homelab-2026/">Nginx Proxy Manager&lt;/a> with a real certificate, or reach it over a tunnel and leave it on the LAN entirely.&lt;/li>
&lt;li>Give it a password you did not reuse.&lt;/li>
&lt;/ul>
&lt;p>If you already run &lt;a href="https://techfuelhq.com/tutorials/uptime-kuma-docker-setup-2026/">Uptime Kuma&lt;/a>, the same reasoning applies there and the same fix works for both.&lt;/p>
&lt;h2 id="puid-and-pgid">PUID and PGID&lt;/h2>
&lt;p>The official file sets both to 1000, and its comment is worth repeating: both must be set for it to do anything. Setting one alone does nothing at all.&lt;/p>
&lt;p>They decide who owns the stack files Dockge writes. Get them wrong and the symptom is undramatic — you SSH in later, try to edit a compose file by hand, and cannot, because it belongs to someone else. &lt;code>id -u&lt;/code> and &lt;code>id -g&lt;/code> give you the right numbers for your own user.&lt;/p>
&lt;h2 id="adopting-stacks-you-already-have">Adopting stacks you already have&lt;/h2>
&lt;p>Dockge reads a directory. There is no import step, and no separate database holding the real state, so a compose file you drop into the stacks directory is simply a stack it can see.&lt;/p>
&lt;p>That property is the reason I find it easy to recommend trying. The compose files are the state. Nothing else is. If you decide against it in a month, you stop the container and your stacks are exactly where you left them, in plain files, unchanged. Tools that own their state are a commitment; this one is a visit.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run the agent/multi-host setup, so I cannot tell you how it behaves when a remote host goes away mid-deploy, which is the case I would want to know about before depending on it.&lt;/p>
&lt;p>I have not measured its resource use, and I would rather say that than quote a figure I did not take.&lt;/p>
&lt;p>I have also not run it against a stack large enough to make the UI struggle, so I do not know where that boundary sits.&lt;/p>
&lt;h2 id="what-getting-the-volume-wrong-costs">What getting the volume wrong costs&lt;/h2>
&lt;p>Not much, if you catch it on day one. You notice the stacks are not where you expected, you fix the bind, you move on.&lt;/p>
&lt;p>The expensive version is catching it in month four, after you have pointed a backup job at &lt;code>/opt/stacks&lt;/code> on the host and it has been faithfully archiving an empty directory the whole time. The compose files were always at &lt;code>/docker&lt;/code>. Nothing errored, because nothing was wrong from any single component&amp;rsquo;s point of view.&lt;/p>
&lt;p>Check the two paths match. Before anything else.&lt;/p></description></item><item><title>Headscale: Self-Hosting the Tailscale Control Server (2026)</title><link>https://techfuelhq.com/networking/headscale-self-hosted-tailscale-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/networking/headscale-self-hosted-tailscale-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~8 min read · St. Louis County, MO&lt;/p>
&lt;p>Most people who look up Headscale want to run it on the machine already humming in their closet. That is the one deployment it does not do.&lt;/p>
&lt;p>Headscale&amp;rsquo;s own requirements page asks for a server with a public IP address, recommends dual-stack IPv4 and IPv6, and serves over HTTPS on port 443 because the Tailscale client assumes that in certain situations. If your home connection sits behind CGNAT, you have no public IP to hand it. If it does have a real public IP, you can technically proceed, and you will have built a coordination server that depends on the same uplink as everything it coordinates.&lt;/p>
&lt;p>So the shape of a Headscale deployment is fixed before you write any config: &lt;strong>a small host somewhere else, with a public address and a name you can put a certificate on.&lt;/strong>&lt;/p>
&lt;p>That is the practical answer. The more useful answer is the next section.&lt;/p>
&lt;h2 id="first-the-case-against-doing-this">First, the case against doing this&lt;/h2>
&lt;p>Tailscale&amp;rsquo;s free Personal plan covers up to 6 users with unlimited user devices, 3 ACL groups, and access to nearly all features. It costs nothing and it is explicitly intended for homelabs and personal projects.&lt;/p>
&lt;p>Read that against your actual situation. One person, a NAS, a Proxmox host, three VMs, a laptop and a phone? You are not close to a limit. There is no bill coming. Headscale would replace a working, maintained, zero-cost service with one you patch, back up, and get paged about.&lt;/p>
&lt;p>I want to be blunt, because the search results for this topic are not: &lt;strong>for the majority of homelabs, Headscale solves a problem you do not have.&lt;/strong> Running it is a hobby in its own right, and that is a completely legitimate reason to run it. It is not the same reason as necessity, and the two get blurred constantly.&lt;/p>
&lt;p>Three situations where it genuinely earns the work:&lt;/p>
&lt;p>&lt;strong>You object to the metadata, not the cost.&lt;/strong> Tailscale&amp;rsquo;s coordination server knows your device names, your public keys, and who connects to what. The traffic is end-to-end encrypted and they cannot read it, but the graph is theirs. If that specific fact is what bothers you, Headscale is a direct answer and no amount of free tier fixes it.&lt;/p>
&lt;p>&lt;strong>Your structure does not fit the Personal plan.&lt;/strong> More than 6 users, or an ACL model that needs more than 3 groups, and you are looking at a paid tier. At that point the comparison is a real one.&lt;/p>
&lt;p>&lt;strong>You want the control plane to survive theirs.&lt;/strong> Existing tailnets keep passing traffic when the coordination server is unreachable, but new nodes and key rotations do not. If your tolerance for that is zero, owning the control plane is the only fix.&lt;/p>
&lt;p>Everything else — &amp;ldquo;self-hosting is better,&amp;rdquo; &amp;ldquo;I want to own my stack&amp;rdquo; — is preference, and preference is fine. Just price it honestly against a free service that already works.&lt;/p>
&lt;h2 id="what-it-does-support">What it does support&lt;/h2>
&lt;p>The 2026 feature list is broad, which surprised me. Node registration by web auth and pre-auth keys, MagicDNS, split DNS and search domains, tags, subnet routers, exit nodes with route filtering, dual-stack, ephemeral nodes, embedded DERP and peer relays, ACLs and grants, autogroups, Tailscale SSH, OIDC single sign-on, Taildrop and Taildrive, Funnel and Serve, network flow logs.&lt;/p>
&lt;p>The documented gap worth checking before you commit: &lt;strong>OIDC groups cannot be used in ACLs.&lt;/strong> If your plan was to point Headscale at your identity provider and let group membership drive access policy, that specific path is closed. Verify it against your intended policy now rather than after you have migrated forty nodes.&lt;/p>
&lt;p>Headscale is not a Tailscale product. It reimplements a protocol it does not control, which is the standing structural risk with anything in this category and is worth naming even though the project has tracked upstream well.&lt;/p>
&lt;h2 id="the-host">The host&lt;/h2>
&lt;p>A control server does very little work. It coordinates key exchange and hands out routes, then gets out of the way while nodes talk directly. SQLite is the assumed database in the setup requirements, so there is no separate database tier to size.&lt;/p>
&lt;p>What it needs is not capacity. It is &lt;em>position&lt;/em>:&lt;/p>
&lt;ul>
&lt;li>A public IPv4 address. Dual-stack with IPv6 is recommended.&lt;/li>
&lt;li>Port 443 reachable, with a valid certificate.&lt;/li>
&lt;li>Uptime that is independent of the network it serves.&lt;/li>
&lt;/ul>
&lt;p>Any small VPS tier meets the first two. The third is the one people undercut by hosting it at home, and it is the whole reason the requirement exists.&lt;/p>
&lt;p>There is one more reason not to put it on your home connection, and it is the sharpest: &lt;strong>if Headscale is the thing that lets you reach your homelab remotely, and Headscale lives in your homelab, then you cannot fix your homelab remotely.&lt;/strong> You have built a mesh VPN whose failure mode is a locked door with the key inside. I would put the control server anywhere except the network it exists to let me into.&lt;/p>
&lt;h2 id="the-domain">The domain&lt;/h2>
&lt;p>HTTPS on 443 means a certificate, and a certificate means a hostname. A subdomain on a domain you already own works fine — nothing about this needs a dedicated registration.&lt;/p>
&lt;p>If you do not own one yet, this is the same purchase you would make for any public service, and it is worth doing before the install rather than during it. Certificate issuance is the step where a missing DNS record turns twenty minutes into an evening.&lt;/p>
&lt;h2 id="where-this-sits-against-the-alternatives">Where this sits against the alternatives&lt;/h2>
&lt;p>If you have not committed yet, the comparison is worth doing properly. I have written up &lt;a href="https://techfuelhq.com/networking/tailscale-vs-wireguard-2026/">Tailscale against plain WireGuard&lt;/a>, which is the real decision for most people, and &lt;a href="https://techfuelhq.com/networking/tailscale-vs-cloudflare-tunnel-2026/">Tailscale against Cloudflare Tunnel&lt;/a> for the case where you want to publish rather than connect. &lt;a href="https://techfuelhq.com/networking/netbird-vs-tailscale-2026/">NetBird against Tailscale&lt;/a> covers the other self-hostable mesh worth a look, and it is the one I would compare Headscale to most carefully, because it was designed to be self-hosted rather than adapted to it.&lt;/p>
&lt;p>If you just want remote access to your homelab today and are not attached to owning the control plane, &lt;a href="https://techfuelhq.com/tutorials/tailscale-remote-access-homelab-2026/">Tailscale on a homelab&lt;/a> takes about ten minutes. If you want no third party in the path at all, &lt;a href="https://techfuelhq.com/tutorials/wireguard-self-hosted-vpn-proxmox-2026/">WireGuard on Proxmox&lt;/a> is the honest floor — more manual, no coordination server to run, no vendor.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run Headscale through a Tailscale client major-version bump, which is the failure mode I would most want data on before recommending it to someone whose remote access depends on it. The project tracks upstream well by reputation. Reputation is not a measurement.&lt;/p>
&lt;p>I have not tested the OIDC integration, so I cannot tell you how painful the ACL group limitation is in practice, only that it is documented.&lt;/p>
&lt;p>I have not run it at a scale where SQLite is the constraint.&lt;/p>
&lt;h2 id="what-getting-this-wrong-costs">What getting this wrong costs&lt;/h2>
&lt;p>The expensive version is not a failed install. It is a successful one, six months ago, on a box in the closet, which you have quietly come to depend on. Then the power blips while you are travelling, and the control server that would have let you back in is the thing that is down.&lt;/p>
&lt;p>Put it somewhere else. That is most of the advice on this page.&lt;/p></description></item><item><title>Monitor Shadow Problem: Three Different Faults Wearing One Name (2026)</title><link>https://techfuelhq.com/articles/monitor-shadow-problem-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/monitor-shadow-problem-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~8 min read · St. Louis County, MO&lt;/p>
&lt;p>Ten feet.&lt;/p>
&lt;p>That is the run length where ViewSonic stops assuming your HDMI cable is fine — and it is the most useful number in this entire topic, because almost nobody staring at a shadowed screen has stopped to think about how long their cable actually is, how many boxes it passes through on the way, or whether the connector behind the monitor has been quietly oxidising in a warm room since 2019. They are thinking about whether the monitor is dying. It usually is not.&lt;/p>
&lt;div class="verdict-card" style="border:1px solid #c8ff00;border-left:4px solid #c8ff00;border-radius:6px;padding:1.25rem 1.5rem;margin:1.5rem 0 2rem 0;background:rgba(200,255,0,0.04);">
&lt;p style="margin:0 0 0.5rem 0;font-weight:700;color:#c8ff00;letter-spacing:0.04em;text-transform:uppercase;font-size:0.85rem;">TL;DR · Find out which shadow you have&lt;/p>
&lt;ul style="margin:0.25rem 0 0 0;padding-left:1.25rem;line-height:1.55;">
&lt;li>&lt;strong>Drag a window across the screen and watch the shadow.&lt;/strong> Everything below depends on this one observation.&lt;/li>
&lt;li>&lt;strong>Holds a fixed offset and follows the window&lt;/strong> &amp;rarr; signal path. Pull the dock, reseat the cable, get off VGA. Cheapest fix on the page.&lt;/li>
&lt;li>&lt;strong>Only appears while things move, gone when still&lt;/strong> &amp;rarr; pixel response time. Different fault, different guide.&lt;/li>
&lt;li>&lt;strong>Faint copy of a taskbar or spreadsheet left up for hours&lt;/strong> &amp;rarr; image persistence. Leave it alone and it goes.&lt;/li>
&lt;li>&lt;strong>Cuts through the monitor's own settings menu&lt;/strong> &amp;rarr; the panel itself, and that menu is the referee.&lt;/li>
&lt;/ul>
&lt;/div>
&lt;p>Most guides on this topic make one mistake, and it is why people replace working monitors. They treat &amp;ldquo;shadow&amp;rdquo;, &amp;ldquo;ghosting&amp;rdquo; and &amp;ldquo;double image&amp;rdquo; as one problem with one list of fixes. Search the phrase and you get a single article covering cables and response time and burn-in in the same breath, as though the reader should simply work down the list until something helps. Those are three faults with nothing in common except the word people reach for when describing them.&lt;/p>
&lt;p>The list approach costs you an evening and, often enough, a monitor.&lt;/p>
&lt;h2 id="the-test-that-decides-everything">The test that decides everything&lt;/h2>
&lt;p>Open any window and drag it slowly across the screen.&lt;/p>
&lt;p>If the duplicate travels with the window and keeps the same offset, the image is being corrupted on its way to the panel. If the duplicate only exists during the drag and the screen is clean the moment you let go, the pixels are switching too slowly. If there is no duplicate at all, and what you are seeing is a faint ghost of yesterday&amp;rsquo;s spreadsheet sitting in one place regardless of what gets dragged over the top of it, then nothing is broken and you can stop worrying.&lt;/p>
&lt;p>Three answers. Skip to yours.&lt;/p>
&lt;h2 id="the-shadow-that-holds-still-your-signal-path">The shadow that holds still: your signal path&lt;/h2>
&lt;p>This is the one worth real attention, because it accounts for most of the searches and it is almost always the cheapest thing in the chain.&lt;/p>
&lt;p>A monitor draws what arrives at its input. It cannot do anything else. When the picture arrives degraded, the panel faithfully draws the degradation, and one of the recognisable ways a video signal degrades is as a displaced, lower-contrast copy of the real image. ViewSonic&amp;rsquo;s own support article on shadowing and double images is blunt about the mechanism: image artifacts are typically caused by signal degradation or interference. That is a panel manufacturer describing its own returns.&lt;/p>
&lt;h3 id="vga-sits-at-the-top-of-the-list">VGA sits at the top of the list&lt;/h3>
&lt;p>Let me be careful about how hard I lean on this.&lt;/p>
&lt;p>I have never put a scope on a VGA line myself, and I am not going to pretend otherwise. What I can tell you is what the manufacturer says, and ViewSonic states plainly that low-quality VGA cables are the most common cause of shadowing, with the recommendation to use HDMI or DisplayPort instead.&lt;/p>
&lt;p>The reasoning holds up. VGA carries the picture as an analogue waveform, so degradation along the way lands directly in what you see — no error correction, no fallback, just a slightly wrong voltage arriving at a panel that has no way of knowing it is wrong. A digital link fails differently. It either delivers a pixel correctly or breaks in ways that look nothing like a soft double image: sparkles, black flashes, a dropped signal, a refresh rate that silently falls back to 30Hz. If you are on VGA and both ends have a spare HDMI or DisplayPort, that swap is a five-minute test which costs nothing and settles the question outright. The catch is that plenty of people are running VGA without knowing it, because a VGA-to-HDMI adapter on a monitor&amp;rsquo;s input, or an old KVM with an analogue backbone, keeps the analogue segment sitting in the middle of the chain while the connector at your desk looks perfectly modern and the box on your shelf says nothing about what it does internally.&lt;/p>
&lt;p>Check the back of the monitor before you rule this out.&lt;/p>
&lt;h3 id="every-box-between-the-two-ends-is-a-suspect">Every box between the two ends is a suspect&lt;/h3>
&lt;p>ViewSonic&amp;rsquo;s first recommended step is to remove any docking stations or video splitters and connect the monitor directly to the PC to test the image quality. That ordering is right, and it is the step people skip, because unplugging a dock means unplugging everything.&lt;/p>
&lt;p>Do it anyway. A dock, a splitter, a KVM and a USB-C hub are all re-driving or re-timing your video, and a cheap one does that badly. If the shadow disappears with the monitor plugged straight into the graphics card, you have found it. You also know what the fix costs, which is the part people want before they start. If you arrived here because a second display was misbehaving too, our guide on a &lt;a href="https://techfuelhq.com/articles/second-monitor-not-detected-2026/">second monitor that will not be detected&lt;/a> covers the same hardware from the other direction.&lt;/p>
&lt;h3 id="length-and-the-one-certification-that-means-something">Length, and the one certification that means something&lt;/h3>
&lt;p>Past about ten feet, cable quality stops being a rounding error. ViewSonic&amp;rsquo;s threshold is three metres, and the recommendation is a Premium Certified HDMI cable or a high-quality shielded one.&lt;/p>
&lt;p>That certification is not marketing. Under the Premium HDMI Cable Certification Program, cables are tested to support the full 18Gbps bandwidth, including an EMI test to make sure they minimise interference with wireless signals, and — this is the part that matters for a long desk run — the program requires every length of every model line to be tested at an official HDMI Authorized Test Center, so a 25-foot cable cannot ride in on the results of its 3-foot sibling. Certified cables carry an anti-counterfeiting label with a QR code you can scan in the shop. That is a meaningfully different claim from &amp;ldquo;high speed&amp;rdquo; printed on a bag.&lt;/p>
&lt;p>DisplayPort has an equivalent worth knowing. VESA&amp;rsquo;s DP8K certification confirms a cable handles HBR3 — the 8.1 Gbps-per-lane rate DisplayPort 1.4 tops out at — verified at an authorised test centre rather than asserted on the packaging. It also checks that pin 20 is not wired through on male-to-male cables. That one is a nastier failure than any shadow, since back-driven power can stop a machine booting.&lt;/p>
&lt;h3 id="then-the-boring-physical-things">Then the boring physical things&lt;/h3>
&lt;p>Reseat both ends. ViewSonic asks you to make sure the connectors are clean, with no oxidation, and are seated properly in the port, which sounds like filler right up until you remember what actually happens to a monitor cable behind a desk: it gets yanked when the desk moves, kinked against a wall, stood on by a chair caster, and left in a warm room for six or seven years while nobody once looks at the pins. Then someone buys a new monitor.&lt;/p>
&lt;p>If none of that moves the needle, bring up the monitor&amp;rsquo;s own on-screen menu while the shadow is visible. That menu is drawn by the monitor&amp;rsquo;s internal board and never touches your cable, so a shadow cutting through the menu overlay puts the fault inside the display. I did not invent that test. It is the same referee our guide to &lt;a href="https://techfuelhq.com/articles/lines-on-monitor-screen-2026/">lines on a monitor screen&lt;/a> uses, and it works here for the same reason.&lt;/p>
&lt;h2 id="the-shadow-that-only-exists-in-motion">The shadow that only exists in motion&lt;/h2>
&lt;p>If the duplicate appears behind moving objects and the screen is clean when nothing moves, stop reading this page. You have ghosting, and this page will not help you. That is a pixel response-time problem inside the panel, and the fix is your monitor&amp;rsquo;s overdrive setting rather than anything in the cable chain. We wrote it up separately in &lt;a href="https://techfuelhq.com/articles/how-to-fix-monitor-ghosting-2026/">how to fix monitor ghosting&lt;/a>.&lt;/p>
&lt;p>One thing is worth flagging, because it is the most common wasted purchase in this whole area. A new cable will do nothing for ghosting. Not one thing. The advice on the two faults points in opposite directions, which is exactly why bundling them into one article does readers harm.&lt;/p>
&lt;h2 id="the-shadow-that-fades-on-its-own">The shadow that fades on its own&lt;/h2>
&lt;p>The third case is a faint copy of something that sat on screen for a long time. A taskbar. A spreadsheet grid. A dashboard someone left up over a weekend.&lt;/p>
&lt;p>That is image persistence, and on an LCD it is temporary. Dell&amp;rsquo;s monitor guidance treats it as a condition that clears once the static content stops being shown, and recommends screen savers and varied content as the prevention. Leave the display on ordinary moving content, or switch it off, and it goes. How long that takes ranges from seconds to considerably longer depending on how long the static image sat there, so patience is genuinely part of the fix here.&lt;/p>
&lt;p>Do not buy anything for this one.&lt;/p>
&lt;p>OLED is the exception, and the distinction matters if you are running a TV as a desktop. There, prolonged static content can produce permanent wear rather than temporary retention. That is a different conversation. There is no home fix.&lt;/p>
&lt;h2 id="the-case-where-the-monitor-is-innocent">The case where the monitor is innocent&lt;/h2>
&lt;p>One search that lands people here has nothing to do with display hardware at all. Windows draws drop shadows under window borders, and a display-scaling change or a graphics-driver reset can render those shadows heavier, or leave them stranded behind inactive windows. If your &amp;ldquo;shadow&amp;rdquo; is a soft grey edge hugging window frames, no cable will touch it.&lt;/p>
&lt;p>So take a screenshot. That settles it in about four seconds, because a real signal or panel fault never survives being captured to a file, while a compositor artifact is baked into the image and will look exactly the same on any other machine you open the file on.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not reproduced any of these faults on a bench for this article, and the sourcing above reflects that: the signal-path claims are ViewSonic&amp;rsquo;s, the cable-certification specifics are HDMI Licensing&amp;rsquo;s and VESA&amp;rsquo;s, and the image-persistence behaviour is Dell&amp;rsquo;s. Where those sources agree with the physics I have said so, and where I am simply relaying a manufacturer&amp;rsquo;s claim I have tried to make that obvious.&lt;/p>
&lt;p>I also cannot tell you how much of the shadowing people report in 2026 is still VGA. ViewSonic&amp;rsquo;s guidance does not carry a date I can check, and analogue connections have been disappearing from new hardware for a decade while surviving in offices, classrooms and KVM setups. The advice holds either way, since the diagnostic sequence does not depend on which cause turns out to be most common.&lt;/p>
&lt;p>The next thing I would measure, if I put a monitor on the bench for this, is whether a failing HDMI run degrades gradually into visible shadowing or falls off a cliff into sparkle and signal loss with nothing in between. My expectation is the cliff, which would make a soft shadow on a short digital cable a much stronger indicator of a dock or adapter problem than of the cable itself.&lt;/p>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>ViewSonic Support, &lt;a href="https://www.viewsonic.com/global/support/article?title=Why&amp;#43;is&amp;#43;there&amp;#43;shadow&amp;#43;or&amp;#43;double&amp;#43;image&amp;#43;on&amp;#43;screen%3F&amp;amp;articleId=33000222422" rel="noopener">&amp;ldquo;Why is there shadow or double image on screen?&amp;rdquo;&lt;/a> — signal degradation as cause, VGA as most common source, dock/splitter removal, three-metre cable threshold, connector oxidation.&lt;/li>
&lt;li>HDMI Licensing Administrator, &lt;a href="https://www.hdmi.org/spec/premiumcable" rel="noopener">Premium HDMI Cable Certification Program&lt;/a> — 18Gbps testing, EMI test, per-length testing at Authorized Test Centers, QR-code authentication label.&lt;/li>
&lt;li>VESA, &lt;a href="https://vesa.org/featured-articles/vesa-strengthens-8k-video-resolution-ecosystem-with-market-ready-dp8k-certified-displayport-cables/" rel="noopener">DP8K certified DisplayPort cables&lt;/a> — HBR3 at 8.1 Gbps per lane, authorised test centre verification, pin 20 checking.&lt;/li>
&lt;li>Dell, &lt;a href="https://www.dell.com/support/kbdoc/en-us/000129648/guidelines-for-dell-monitor-usage-to-prevent-image-retention-and-preserve-panel-life" rel="noopener">Guidelines for Dell Monitor Usage to Prevent Image Retention and Preserve Panel Life&lt;/a> — image retention as a temporary LCD condition, prevention guidance.&lt;/li>
&lt;/ul></description></item><item><title>Ollama in Docker with GPU: Stop Installing CUDA Inside WSL2 (2026)</title><link>https://techfuelhq.com/tutorials/ollama-docker-gpu-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/ollama-docker-gpu-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~9 min read · St. Louis County, MO&lt;/p>
&lt;p>If you are on WSL2, the most common first move is the wrong one, and it feels like progress while you make it.&lt;/p>
&lt;p>People open the distro, run &lt;code>apt install cuda&lt;/code> or &lt;code>cuda-drivers&lt;/code>, check &lt;code>nvcc --version&lt;/code>, see a version string, and treat the prerequisite as handled.&lt;/p>
&lt;p>NVIDIA&amp;rsquo;s own CUDA-on-WSL documentation warns against exactly this. More than once. One of those warnings is in capitals.&lt;/p>
&lt;p>Here is why it is not merely unnecessary but harmful. Under WSL2 the &lt;strong>Windows&lt;/strong> driver is projected into the distro as a &lt;code>libcuda.so&lt;/code> stub. That stub &lt;em>is&lt;/em> the GPU access path. The &lt;code>cuda&lt;/code>, &lt;code>cuda-12-x&lt;/code> and &lt;code>cuda-drivers&lt;/code> meta-packages pull in a Linux NVIDIA driver, which installs &lt;em>over&lt;/em> that stub and breaks the thing that was working.&lt;/p>
&lt;p>You do not need a driver inside WSL. You already have one. It came from Windows.&lt;/p>
&lt;h2 id="the-two-toolkits-people-conflate">The two toolkits people conflate&lt;/h2>
&lt;p>This is the root of it. The naming is genuinely unhelpful:&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Package&lt;/th>
&lt;th scope="col">What it does&lt;/th>
&lt;th scope="col">Needed for Ollama in Docker?&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>CUDA Toolkit&lt;/strong> (&lt;code>nvcc&lt;/code>, headers)&lt;/td>
&lt;td>compiles CUDA applications&lt;/td>
&lt;td>No&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>NVIDIA Container Toolkit&lt;/strong> (&lt;code>nvidia-container-toolkit&lt;/code>)&lt;/td>
&lt;td>lets Docker hand a GPU to a container&lt;/td>
&lt;td>&lt;strong>Yes&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>They share a brand. Nothing else. &lt;code>nvcc --version&lt;/code> printing happily tells you precisely nothing about whether Docker can reach your GPU — I have watched that exact screenshot get posted as evidence in bug reports where the real failure was that the container toolkit was never installed.&lt;/p>
&lt;p>You want the second one.&lt;/p>
&lt;p>On Debian or Ubuntu:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl -fsSL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> | sed &lt;span style="color:#e6db74">&amp;#39;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&amp;#39;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get install -y nvidia-container-toolkit
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is the same package on native Linux and inside WSL2. The only difference is where you stop: on WSL2 that command is the end of it, whereas on native Linux you also need a real NVIDIA driver underneath, which is the step WSL2 users are trying to replicate when they break their stub.&lt;/p>
&lt;h2 id="running-it">Running it&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run -d --gpus&lt;span style="color:#f92672">=&lt;/span>all &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -v ollama:/root/.ollama &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -p 11434:11434 &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --name ollama ollama/ollama
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec -it ollama ollama run llama3.2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Drop &lt;code>--gpus=all&lt;/code> and you get a working CPU install. That is a reasonable first move: it confirms the rest of your setup before you start fighting the GPU layer, and it means a later failure has exactly one new variable in it.&lt;/p>
&lt;p>For AMD, the image and the flags both change:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run -d --device /dev/kfd --device /dev/dri &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -v ollama:/root/.ollama -p 11434:11434 &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --name ollama ollama/ollama:rocm
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note the volume is named.&lt;/p>
&lt;p>&lt;code>/root/.ollama&lt;/code> holds your downloaded models, and those are large. An anonymous volume there is how people re-download forty gigabytes after a cleanup — see &lt;a href="https://techfuelhq.com/tutorials/docker-cleanup-disk-space-2026/">which prune command eats data&lt;/a> for why that happens.&lt;/p>
&lt;h2 id="where-11434-really-listens">Where 11434 really listens&lt;/h2>
&lt;p>There is bad advice in circulation. It says Ollama binds &lt;code>127.0.0.1&lt;/code> by default, so publishing the port is safe.&lt;/p>
&lt;p>That is true of a native install. It is not true of this image. The official container sets &lt;code>OLLAMA_HOST=0.0.0.0:11434&lt;/code> in its Dockerfile, so inside the container it listens on everything, and whatever you publish with &lt;code>-p&lt;/code> is genuinely reachable.&lt;/p>
&lt;p>Ollama&amp;rsquo;s API has no authentication. &lt;code>-p 11434:11434&lt;/code> on a machine with a public IP publishes an unauthenticated inference endpoint on someone else&amp;rsquo;s hardware budget. Bind it to localhost explicitly if you want it host-only:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>-p 127.0.0.1:11434:11434
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="compose-where---gpus-does-not-exist">Compose, where &lt;code>--gpus&lt;/code> does not exist&lt;/h2>
&lt;p>This is the second thing that costs people an evening.&lt;/p>
&lt;p>&lt;code>--gpus=all&lt;/code> is a &lt;code>docker run&lt;/code> flag. Compose does not accept it as a service key, and the error you get does not point anywhere useful.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ollama&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">ollama/ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">ollama:/root/.ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;127.0.0.1:11434:11434&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">deploy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">resources&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">reservations&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">devices&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">driver&lt;/span>: &lt;span style="color:#ae81ff">nvidia&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">count&lt;/span>: &lt;span style="color:#ae81ff">all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">capabilities&lt;/span>: [&lt;span style="color:#ae81ff">gpu]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ollama&lt;/span>:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Two rules inside that block, both documented and both easy to trip:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>capabilities&lt;/code> is not optional.&lt;/strong> Docker&amp;rsquo;s docs state that omitting it errors on service deployment. It looks like decoration and it is required.&lt;/li>
&lt;li>&lt;strong>&lt;code>count&lt;/code> and &lt;code>device_ids&lt;/code> are mutually exclusive.&lt;/strong> Pick one, or it errors.&lt;/li>
&lt;/ul>
&lt;p>There is also a newer top-level &lt;code>gpus:&lt;/code> attribute if your Compose version has it, which is less verbose for the common case.&lt;/p>
&lt;h2 id="the-wsl2-restriction-nobody-mentions">The WSL2 restriction nobody mentions&lt;/h2>
&lt;p>On WSL2, NVIDIA documents that only &lt;code>--gpus all&lt;/code> is supported.&lt;/p>
&lt;p>You cannot filter by index or UUID.&lt;/p>
&lt;p>So a compose file pinning &lt;code>device_ids: ['0']&lt;/code> is documented as not workable under WSL2, even though the identical file is fine on native Linux. If you have two GPUs in a Windows box and were planning to give one to Ollama and keep the other for something else, that plan does not survive contact with WSL2.&lt;/p>
&lt;p>That single limitation is the strongest argument I know for putting the LLM host on native Linux rather than WSL2, assuming you have the choice, and it is the kind of constraint that only shows up after you have already built the thing around the assumption that a GPU is a GPU.&lt;/p>
&lt;h2 id="adding-open-webui">Adding Open WebUI&lt;/h2>
&lt;p>The obvious next step is a browser interface. Open WebUI&amp;rsquo;s official stack runs it alongside Ollama, and their &lt;code>:cuda&lt;/code> image tag is documented as Nvidia GPU support, to be paired with &lt;code>--gpus all&lt;/code>.&lt;/p>
&lt;p>One deliberate default worth understanding before you &amp;ldquo;fix&amp;rdquo; it: in Open WebUI&amp;rsquo;s official compose stack, &lt;strong>the ollama service publishes no host port at all.&lt;/strong> 11434 is reachable on the Compose network and nowhere else. That is not an oversight. It means the only thing exposed is the UI, which has accounts, rather than the raw API, which does not.&lt;/p>
&lt;p>If you genuinely need the API from the host, they ship a separate api overlay for that. Use it rather than editing the base file, so the reason stays visible.&lt;/p>
&lt;h2 id="verifying-the-gpu-is-doing-the-work">Verifying the GPU is doing the work&lt;/h2>
&lt;p>The failure mode here is quiet. Everything runs. It just runs slowly, on the CPU, while you assume otherwise.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker exec -it ollama nvidia-smi
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If that errors, the container cannot see the GPU and no amount of Ollama configuration will help — the problem is the container toolkit or the driver.&lt;/p>
&lt;p>Then run a prompt and watch &lt;code>nvidia-smi&lt;/code> on the host. If VRAM use does not move and your CPU fans do, the model is not on the GPU. The usual cause is that the model does not fit in VRAM, which is a hardware question rather than a Docker one, and which I have written up separately in &lt;a href="https://techfuelhq.com/articles/local-llm-by-gpu-vram-2026/">local LLMs by GPU VRAM&lt;/a>.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run the ROCm image. The command above comes from Ollama&amp;rsquo;s documentation and I have no AMD card here to confirm it against, so treat that line as documented rather than verified by me.&lt;/p>
&lt;p>I have not tested the newer top-level &lt;code>gpus:&lt;/code> Compose attribute, and Compose version support for it is exactly the sort of thing that varies by distro package.&lt;/p>
&lt;p>I have not benchmarked WSL2 against native Linux for inference throughput. I believe native is better and I have not measured it, so I am not going to give you a number.&lt;/p>
&lt;h2 id="what-getting-it-wrong-costs">What getting it wrong costs&lt;/h2>
&lt;p>The CUDA-inside-WSL mistake costs you a working GPU and then several hours, because the symptom appears &lt;em>after&lt;/em> the install that felt like progress. You were closer before you started than after.&lt;/p>
&lt;p>The &lt;code>-p 11434:11434&lt;/code> mistake costs more, and it costs it quietly. An unauthenticated inference API on a public address does not announce itself. It just becomes somebody else&amp;rsquo;s free GPU until you notice the electricity bill or the fan noise.&lt;/p></description></item><item><title>SSH Port Forwarding: -L, -R, -D and Why Your Reverse Tunnel Only Works Locally (2026)</title><link>https://techfuelhq.com/networking/ssh-port-forwarding-tunneling-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/networking/ssh-port-forwarding-tunneling-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~10 min read · St. Louis County, MO&lt;/p>
&lt;p>Three flags. The third is where the afternoon goes.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -L 8080:internal-host:80 user@server &lt;span style="color:#75715e"># reach IN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ssh -R 8080:localhost:80 user@server &lt;span style="color:#75715e"># expose OUT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ssh -D &lt;span style="color:#ae81ff">1080&lt;/span> user@server &lt;span style="color:#75715e"># SOCKS proxy&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>-L&lt;/code> opens a listener on &lt;strong>your&lt;/strong> machine. &lt;code>-R&lt;/code> opens one on &lt;strong>the server&lt;/strong>. That is the entire difference. Inverting it is the beginner mistake, and it announces itself immediately, which makes it the cheap one.&lt;/p>
&lt;p>The expert mistake is different, and it is the reason this page exists: &lt;strong>&lt;code>-R&lt;/code> does not fail when it does not work.&lt;/strong> It succeeds into a state that is not the one you asked for.&lt;/p>
&lt;h2 id="the--r-trap">The -R trap&lt;/h2>
&lt;p>You run this on a home machine, against a VPS with a public IP:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -R 8080:localhost:80 user@vps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You expect &lt;code>http://vps-public-ip:8080&lt;/code> to reach the web server at home. From the VPS itself, &lt;code>curl localhost:8080&lt;/code> works perfectly, which is the detail that sends people off debugging their home firewall, their router, and eventually their ISP, when none of those were ever in the path. From anywhere else: connection refused.&lt;/p>
&lt;p>Nothing errored. The tunnel is up. It is bound to &lt;code>127.0.0.1&lt;/code> on the VPS, which is a perfectly good place for a listener to be if that is what you asked for, and you did not.&lt;/p>
&lt;p>That is sshd&amp;rsquo;s documented default. Remote forwards bind loopback unless &lt;code>GatewayPorts&lt;/code> is enabled, and it defaults to &lt;code>no&lt;/code>.&lt;/p>
&lt;p>Then comes the second half, which is the part that costs the extra hour. You reasonably try to force it from the client:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -R 0.0.0.0:8080:localhost:80 user@vps &lt;span style="color:#75715e"># still loopback-only&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It does not help.&lt;/p>
&lt;p>&lt;code>ssh(1)&lt;/code> is explicit: specifying a remote bind_address will only succeed if the server&amp;rsquo;s GatewayPorts option is enabled. Your bind address is a request, not an instruction — the server is free to override it, and by default it does exactly that, binding loopback anyway rather than refusing the forward and saying why. A refusal would have cost you thirty seconds. The override costs you the evening.&lt;/p>
&lt;p>This is documented in OpenSSH&amp;rsquo;s own tracker as bug 1297, filed by someone who noticed the socket was always bound to &lt;code>127.0.0.1&lt;/code> and &lt;code>[::1]&lt;/code> and that &lt;code>-L&lt;/code> had no such problem. That is the shape of the confusion: local forwards obey you, remote forwards negotiate with a server whose defaults you did not read.&lt;/p>
&lt;h2 id="fixing-it-on-the-correct-side">Fixing it, on the correct side&lt;/h2>
&lt;p>On the &lt;strong>server&lt;/strong>, in &lt;code>sshd_config&lt;/code>:&lt;/p>
&lt;pre tabindex="0">&lt;code>GatewayPorts clientspecified
&lt;/code>&lt;/pre>&lt;p>Then reload sshd. Not your session. The daemon.&lt;/p>
&lt;p>I recommend &lt;code>clientspecified&lt;/code> over &lt;code>yes&lt;/code> deliberately. &lt;code>yes&lt;/code> forces remote forwards to bind the wildcard address for &lt;strong>every&lt;/strong> client on that server — a blunt, global change that removes the option of a loopback-only forward from everyone. &lt;code>clientspecified&lt;/code> gives each client the choice, so &lt;code>-R 0.0.0.0:8080:...&lt;/code> binds wide and a plain &lt;code>-R 8080:...&lt;/code> stays local.&lt;/p>
&lt;h3 id="the-two-gatewayports">The two GatewayPorts&lt;/h3>
&lt;p>Here is the detail that turns a five-minute fix into a long one, and it is purely a naming accident.&lt;/p>
&lt;p>There are &lt;strong>two&lt;/strong> &lt;code>GatewayPorts&lt;/code> options with near-identical wording:&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">File&lt;/th>
&lt;th scope="col">Governs&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>sshd_config&lt;/code> (server)&lt;/td>
&lt;td>&lt;code>-R&lt;/code> listeners the server opens on your behalf&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ssh_config&lt;/code> (client)&lt;/td>
&lt;td>your own &lt;code>-L&lt;/code> and &lt;code>-D&lt;/code> listeners&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>They live in different files, on different machines, and do different jobs. Editing the client one, reloading nothing, and then wondering for forty minutes why the reverse tunnel is still loopback-only is an experience I would rather you skip.&lt;/p>
&lt;p>Debugging &lt;code>-R&lt;/code>? Server file. Every time.&lt;/p>
&lt;h2 id="-l-properly">-L, properly&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -L &lt;span style="color:#f92672">[&lt;/span>bind_address:&lt;span style="color:#f92672">]&lt;/span>port:host:hostport destination
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>host:hostport&lt;/code> is resolved from the server&amp;rsquo;s perspective, and that is the entire point of the flag: you are borrowing the server&amp;rsquo;s view of the network for the duration of the session, which is why it reaches things your own machine has no route to. This reaches a NAS at &lt;code>192.168.1.50&lt;/code> that your laptop cannot route to:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -L 8080:192.168.1.50:80 user@homelab-gateway
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then browse &lt;code>localhost:8080&lt;/code>. That is it.&lt;/p>
&lt;p>By default that listener binds loopback on your machine, so nobody else on the coffee-shop wifi can use your tunnel. That default is correct. Leave it.&lt;/p>
&lt;p>&lt;code>-L&lt;/code> also accepts Unix sockets on either end, which is how you reach a socket-only service like a database or a Docker daemon without publishing a TCP port for it.&lt;/p>
&lt;h2 id="-d-the-one-people-underuse">-D, the one people underuse&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -D &lt;span style="color:#ae81ff">1080&lt;/span> user@server
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That is a local SOCKS 4/5 listener. Point a browser&amp;rsquo;s SOCKS proxy at &lt;code>localhost:1080&lt;/code> and its traffic emerges from the server, with DNS resolved there too if the client is configured for remote DNS.&lt;/p>
&lt;p>I reach for this more than &lt;code>-L&lt;/code> when I am poking at a homelab, because it needs no per-service forwards. One flag, and the whole network is reachable by its internal names for as long as the session lives.&lt;/p>
&lt;p>It is not a VPN. It carries only what an application deliberately sends through the proxy, so anything not SOCKS-aware ignores it completely and silently, which is a distinction people discover at the worst possible moment. If you want everything routed, you want &lt;a href="https://techfuelhq.com/tutorials/wireguard-self-hosted-vpn-proxmox-2026/">WireGuard&lt;/a> or &lt;a href="https://techfuelhq.com/networking/tailscale-vs-wireguard-2026/">Tailscale&lt;/a>, not this.&lt;/p>
&lt;h2 id="-j-which-is-not-a-tunnel-at-all">-J, which is not a tunnel at all&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ssh -J bastion.example.com user@internal-host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>ProxyJump reaches a final destination &lt;em>through&lt;/em> an intermediate. Nothing is published, no listener opens, and the bastion does not see your session in cleartext — your client negotiates end-to-end with the real target.&lt;/p>
&lt;p>Keep the distinction clean.&lt;/p>
&lt;ul>
&lt;li>Administrative access to a machine behind a bastion is a &lt;strong>&lt;code>-J&lt;/code>&lt;/strong> job.&lt;/li>
&lt;li>Exposing a service is a &lt;strong>&lt;code>-L&lt;/code>&lt;/strong> or &lt;strong>&lt;code>-R&lt;/code>&lt;/strong> job.&lt;/li>
&lt;/ul>
&lt;p>I have watched people build an elaborate &lt;code>-L&lt;/code> chain for something &lt;code>-J&lt;/code> does in one flag, in &lt;code>~/.ssh/config&lt;/code>, permanently:&lt;/p>
&lt;pre tabindex="0">&lt;code>Host internal-*
ProxyJump bastion.example.com
&lt;/code>&lt;/pre>&lt;h2 id="administratively-prohibited">&amp;ldquo;administratively prohibited&amp;rdquo;&lt;/h2>
&lt;pre tabindex="0">&lt;code>channel 3: open failed: administratively prohibited
&lt;/code>&lt;/pre>&lt;p>Two things about this message. The first one saves you a search.&lt;/p>
&lt;p>First: the &lt;code>3&lt;/code> is meaningless. It is OpenSSH&amp;rsquo;s local channel id from a format string. Searching the literal message &lt;em>with the number in it&lt;/em> is why people find nothing.&lt;/p>
&lt;p>Second: it means the server refused. Almost nothing more. There are at least three distinct causes, all server-side:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>AllowTcpForwarding&lt;/code>&lt;/strong> in &lt;code>sshd_config&lt;/code> disallowing that direction. It takes &lt;code>local&lt;/code> and &lt;code>remote&lt;/code> as values, not just yes and no, so a server can permit &lt;code>-L&lt;/code> and refuse &lt;code>-R&lt;/code>.&lt;/li>
&lt;li>&lt;strong>A key option in &lt;code>authorized_keys&lt;/code>&lt;/strong> — &lt;code>no-port-forwarding&lt;/code>, or &lt;code>restrict&lt;/code>, which turns everything off and then re-enables only what you name after it.&lt;/li>
&lt;li>&lt;strong>&lt;code>permitopen&lt;/code> / &lt;code>PermitOpen&lt;/code>&lt;/strong> restricting forwards to a specific host and port list that does not include the one you asked for.&lt;/li>
&lt;/ol>
&lt;p>Check them in that order. The &lt;code>authorized_keys&lt;/code> case catches people out most often, because the server&amp;rsquo;s global config reads permissive and the restriction is sitting on the key itself, which is not where anyone looks second.&lt;/p>
&lt;h2 id="privileged-ports-behave-differently-by-direction">Privileged ports behave differently by direction&lt;/h2>
&lt;p>&lt;code>ssh(1)&lt;/code> gives two different rules, and they are easy to conflate:&lt;/p>
&lt;ul>
&lt;li>For &lt;code>-L&lt;/code>: only the superuser can forward privileged ports. That is on &lt;strong>your&lt;/strong> side.&lt;/li>
&lt;li>For &lt;code>-R&lt;/code>: privileged ports can be forwarded only when logging in as root on the remote machine. That is on &lt;strong>the server&amp;rsquo;s&lt;/strong> side.&lt;/li>
&lt;/ul>
&lt;p>So &lt;code>-R 80:localhost:8080&lt;/code> to a VPS fails unless you are logging in as root there, which you should not be. Bind something above 1024 and put a &lt;a href="https://techfuelhq.com/tutorials/nginx-proxy-manager-homelab-2026/">reverse proxy&lt;/a> in front of it.&lt;/p>
&lt;h2 id="keeping-a-tunnel-alive">Keeping a tunnel alive&lt;/h2>
&lt;p>An SSH tunnel is a process. Processes die. For anything you depend on, put it under supervision rather than in a terminal you will eventually close:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ini" data-lang="ini">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/systemd/system/tunnel.service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">[Service]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ExecStart&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">/usr/bin/ssh -N -T -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> -R 8080:localhost:80 user@vps&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">Restart&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">always&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">RestartSec&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">10&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>-N&lt;/code> runs no remote command, &lt;code>-T&lt;/code> allocates no TTY. &lt;code>ExitOnForwardFailure=yes&lt;/code> earns its place: without it, ssh happily stays connected when a forward could not be established, and systemd sees a healthy process fronting a tunnel that carries nothing.&lt;/p>
&lt;p>&lt;code>ServerAliveInterval&lt;/code> matters because an idle tunnel crossing a NAT gateway is exactly the kind of connection a middlebox reaps without telling either end, leaving you with a socket that looks established on both sides and moves nothing.&lt;/p>
&lt;h2 id="where-this-stops-being-the-right-tool">Where this stops being the right tool&lt;/h2>
&lt;p>Reverse tunnels are the classic answer to &amp;ldquo;my home connection has no public IP&amp;rdquo;, and for one or two services they remain a genuinely good one, because the alternative is standing up infrastructure to solve a problem that a single flag already solves. They work. I still keep one for a couple of things.&lt;/p>
&lt;p>But if you find yourself maintaining several, plus a systemd unit for each, plus &lt;code>GatewayPorts&lt;/code> on a server whose config you now have to remember, you have hand-built a worse mesh VPN. That is the point to look at &lt;a href="https://techfuelhq.com/networking/tailscale-vs-wireguard-2026/">Tailscale or WireGuard&lt;/a>, or at &lt;a href="https://techfuelhq.com/networking/headscale-self-hosted-tailscale-2026/">running the control plane yourself&lt;/a>.&lt;/p>
&lt;p>The honest dividing line I use is this. One or two forwards, occasional, and &lt;code>-R&lt;/code> is fine.&lt;/p>
&lt;p>More than that, or anything a household depends on, and the tunnel collection has quietly become technical debt with a systemd unit attached to each piece.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not verified whether a current client surfaces the loopback downgrade under &lt;code>-v&lt;/code>. OpenSSH added a debug message for this case in the 6.4 era, and I could not establish from the sources I read whether that reliably reaches a modern user&amp;rsquo;s terminal. Assume it is silent and check the listener yourself with &lt;code>ss -tlnp&lt;/code> on the server.&lt;/p>
&lt;p>I have not tested any of the &lt;code>authorized_keys&lt;/code> restriction interactions on a live sshd during this write-up, so treat the ordering advice as a plan of attack rather than a measured result.&lt;/p>
&lt;h2 id="what-getting-it-wrong-costs">What getting it wrong costs&lt;/h2>
&lt;p>The &lt;code>-R&lt;/code> trap costs an evening. That is the good outcome: you conclude nothing works, and go read the docs.&lt;/p>
&lt;p>The bad outcome is &lt;code>GatewayPorts yes&lt;/code> set globally on a server, forgotten, on a box that also hosts something else. Now every remote forward any account opens binds the wildcard address by default. Somebody tunnels an admin panel out to test something, leaves it up, and there is a listener on a public IP that nobody remembers creating.&lt;/p>
&lt;p>&lt;code>clientspecified&lt;/code> costs nothing extra and does not accumulate that debt.&lt;/p></description></item><item><title>Uptime Kuma Docker Setup, and Where to Actually Run It (2026)</title><link>https://techfuelhq.com/tutorials/uptime-kuma-docker-setup-2026/</link><pubDate>Sat, 15 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/tutorials/uptime-kuma-docker-setup-2026/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · 2026-08-15 · ~9 min read · St. Louis County, MO&lt;/p>
&lt;p>Uptime Kuma installs in about ninety seconds. One container, one volume, one port. That part is genuinely easy, and every guide covers it.&lt;/p>
&lt;p>Here is the part that decides whether the install was worth doing: &lt;strong>a monitor that lives inside the network it watches cannot tell you that network went down.&lt;/strong> Put Kuma on your Proxmox box, point it at your NAS, your Jellyfin, your reverse proxy, and go to bed happy. Then the UPS gives up at 3am. Everything stops, including Kuma. Your phone stays quiet all night, because the thing whose job was to shout is on the floor with everything else.&lt;/p>
&lt;p>You find out at 9am. The dashboard shows a clean green wall, because it has no memory of the hours it spent unpowered, and a gap in the record renders identically to a stretch of perfect health once the container comes back and resumes drawing bars.&lt;/p>
&lt;p>I have watched people run this setup for months and conclude their homelab is extremely reliable. It wasn&amp;rsquo;t.&lt;/p>
&lt;h2 id="the-install-briefly">The install, briefly&lt;/h2>
&lt;p>Version 2.5.0 shipped on 1 August 2026. Pin the major tag.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uptime-kuma&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">louislam/uptime-kuma:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">uptime-kuma&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;3001:3001&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./data:/app/data&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>mkdir -p /opt/uptime-kuma/data &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> cd /opt/uptime-kuma
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker compose up -d
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Open port 3001 and create the admin account on first load. That&amp;rsquo;s it. There is no separate database container. Kuma uses SQLite inside that one data volume, which is why this compose file is four lines of service definition instead of the five-container arrangement a &lt;a href="https://techfuelhq.com/tutorials/paperless-ngx-docker-setup-2026/">Paperless-ngx stack&lt;/a> needs. Version 2.x can talk to other backends for large deployments. For a homelab watching a few dozen endpoints, SQLite is correct and it is one fewer thing that can fail at 3am.&lt;/p>
&lt;p>Do not publish 3001 to the internet. It is a login page standing in front of a complete map of your infrastructure, including hostnames and internal ports you would rather not advertise. Put it behind &lt;a href="https://techfuelhq.com/tutorials/nginx-proxy-manager-homelab-2026/">Nginx Proxy Manager&lt;/a> or reach it over a &lt;a href="https://techfuelhq.com/networking/tailscale-vs-wireguard-2026/">WireGuard or Tailscale tunnel&lt;/a>.&lt;/p>
&lt;p>That is the whole tutorial. The rest of this page is about placement, which is where the value is.&lt;/p>
&lt;h2 id="why-placement-is-the-whole-problem">Why placement is the whole problem&lt;/h2>
&lt;p>Uptime Kuma measures reachability. It sends a request and reports whether something answered. Every result it produces is therefore relative to one specific position on the network — its own.&lt;/p>
&lt;p>From inside your LAN, Kuma can see that Jellyfin&amp;rsquo;s container is answering on port 8096. That is a real and useful fact. It is not the fact your users have. Your users are outside, and between them and Jellyfin sits your ISP, your modem, your router&amp;rsquo;s NAT and port forwarding, your DNS records, your certificate expiry, and your reverse proxy. Kuma checking &lt;code>http://192.168.1.40:8096&lt;/code> validates exactly one link in that chain and silently vouches for the rest.&lt;/p>
&lt;p>So there are two distinct failure classes. One monitor position cannot cover both, and the table below is the reason I stopped treating a single green dashboard as evidence of anything.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Failure&lt;/th>
&lt;th scope="col">Seen from inside&lt;/th>
&lt;th scope="col">Seen from outside&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Container crashed&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Disk full, service refusing writes&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Certificate expired&lt;/td>
&lt;td>no&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>DNS record wrong or lapsed&lt;/td>
&lt;td>no&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ISP down, modem dead, power cut&lt;/td>
&lt;td>&lt;strong>no — monitor is down too&lt;/strong>&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Port forward removed by a firmware update&lt;/td>
&lt;td>no&lt;/td>
&lt;td>yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VPN tunnel to the monitor collapsed&lt;/td>
&lt;td>n/a&lt;/td>
&lt;td>shows as a false outage&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>The bottom-left cell is the one that matters. When the whole site loses power, an internal monitor does not report an outage. It reports nothing at all, and nothing looks exactly like fine.&lt;/p>
&lt;h2 id="two-placements-that-work">Two placements that work&lt;/h2>
&lt;p>&lt;strong>Primary outside, pointed in.&lt;/strong> Run Kuma on a small external host and monitor your public endpoints the way a stranger would. This is the setup I would pick if I were only running one instance. It catches expired certificates, broken DNS, dead port forwards, and total site loss, because it is not standing on any of the things that break. Requirements are modest, which is the useful part: Kuma is a single Node process with a SQLite file, so the smallest tier at any VPS host is enough to watch a homelab&amp;rsquo;s worth of endpoints.&lt;/p>
&lt;p>The trade is real. An outside instance sees only what you publish, so anything you never exposed to the internet is invisible to it, and that is usually most of the stack.&lt;/p>
&lt;p>&lt;strong>Two instances, watching each other.&lt;/strong> Keep the detailed instance inside, where it can reach every container and internal port. Add a second, nearly empty instance outside whose entire job is to watch the first one and a couple of public endpoints. Point each at the other&amp;rsquo;s health endpoint. Now an outage has to take out two separate sites and two separate uplinks before you hear silence.&lt;/p>
&lt;p>This is the arrangement I would run for anything I actually cared about, and it costs one small VPS.&lt;/p>
&lt;p>Do not try to solve this by having the outside instance reach in over a tunnel to check internal services. It sounds tidy. It fails badly, and in a specific way: the tunnel becomes a shared dependency, so every tunnel hiccup fires as a simultaneous outage across a dozen unrelated monitors, and after two weeks of that you will start ignoring the alerts. Which is worse than not having them.&lt;/p>
&lt;h2 id="the-push-monitor-is-the-one-people-skip">The push monitor is the one people skip&lt;/h2>
&lt;p>Most Kuma monitors ask a question outward. The push monitor inverts that — it hands you a URL and waits to be called.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># at the end of your backup script&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>restic backup /data --repo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$REPO&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> curl -fsS &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$KUMA_PUSH_URL&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the script finishes, Kuma hears from it. Good. If the script fails, hangs, or was never scheduled because the cron entry got clobbered, the call never arrives and Kuma alerts on the silence.&lt;/p>
&lt;p>This catches a class of problem that no reachability check will ever see. Your backup host can be up, healthy, answering pings, and passing every HTTP check while quietly not having produced a backup in five weeks. I would put a push monitor on every scheduled job whose failure you would not notice for a month. Backups first.&lt;/p>
&lt;h2 id="notification-settings-that-avoid-making-you-ignore-it">Notification settings that avoid making you ignore it&lt;/h2>
&lt;p>The defaults are tuned to demonstrate the feature, not to survive contact with a homelab that reboots.&lt;/p>
&lt;p>Set &lt;strong>Heartbeat Interval&lt;/strong> to how fast you could genuinely respond. Sixty seconds is a reasonable floor. Set &lt;strong>Retries&lt;/strong> to at least 3 before a monitor is marked down, so a container restart does not page you. Sixty seconds with 3 retries gives a service three minutes to come back on its own, which covers nearly every routine restart.&lt;/p>
&lt;p>Add at least two notification channels through different infrastructure. Kuma supports over ninety providers. The reason for two is narrow but real: if you route everything through one service and that service is the thing that broke, your alert about the outage is part of the outage.&lt;/p>
&lt;p>Then leave it alone for a week and count how many notifications you received that you did not act on. Every one of those is training you to dismiss the next one. Raise the retries until that count is near zero.&lt;/p>
&lt;h2 id="the-status-page-and-whether-you-need-a-domain">The status page, and whether you need a domain&lt;/h2>
&lt;p>Kuma&amp;rsquo;s status pages are genuinely good and cost nothing to set up. Group your monitors, mark which ones are public, and publish.&lt;/p>
&lt;p>You need a hostname for it if the audience is anyone other than you. A status page at an IP address with a certificate warning does not reassure the household that the media server is coming back. If you are already buying a domain for your reverse proxy, a &lt;code>status.&lt;/code> subdomain on it is free and takes about two minutes.&lt;/p>
&lt;p>If the audience is only you, skip the domain and reach it over the tunnel.&lt;/p>
&lt;h2 id="what-i-have-not-tested">What I have not tested&lt;/h2>
&lt;p>I have not run Kuma at a scale where SQLite is the constraint, so I cannot tell you where that boundary sits or whether moving to MariaDB is worth the extra container. Everything above is from homelab-scale use — dozens of monitors, not hundreds.&lt;/p>
&lt;p>I have not measured Kuma&amp;rsquo;s resource use on the very smallest VPS tiers, and I would rather say that than quote a RAM figure I did not take. It is a single Node process with a SQLite file, so the tier below whatever you were considering is probably fine, but &amp;ldquo;probably&amp;rdquo; is doing real work in that sentence.&lt;/p>
&lt;p>The 2.x non-SQLite backends I have not touched at all.&lt;/p>
&lt;h2 id="what-getting-this-wrong-costs">What getting this wrong costs&lt;/h2>
&lt;p>A silent monitor is worse than no monitor, because it converts an unknown into a false negative. You stop checking manually. You stop being suspicious. Then a drive fails in a mirror and the array runs degraded for three weeks, and the second drive fails, and the honest answer to &amp;ldquo;when did this start&amp;rdquo; is that nobody knows.&lt;/p>
&lt;p>The install is ninety seconds. The placement decision is the part that determines whether any of it works, and it is the part almost every guide leaves out — including, for about a year, mine.&lt;/p></description></item><item><title>GPU Fans Stuck at 100%: The Fix Order That Finds the Cause</title><link>https://techfuelhq.com/articles/gpu-fans-stuck-at-100-percent/</link><pubDate>Thu, 13 Aug 2026 09:20:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/gpu-fans-stuck-at-100-percent/</guid><description>&lt;p>Fans pinned at 100% feel like an emergency because of the noise, but the noise is the least informative part. A modern card only commands full speed for a handful of reasons, most of them software, and the fastest path out is to check them in the order below — cheapest and most common first — instead of opening the case with a screwdriver on cause number six.&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/gpu-fan-curve-stuck-100.svg" alt="Diagram of fan duty versus GPU temperature: a healthy curve sits at zero RPM below about 50C then ramps smoothly to 100 percent near 95C, while a stuck card draws a flat 100 percent line across every temperature, labeled a control failure" width="1200" height="640" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="first-two-situations-where-full-speed-is-correct">First: two situations where full speed is correct&lt;/h2>
&lt;p>&lt;strong>Before the driver loads.&lt;/strong> From power-on until the graphics driver initializes, there is no fan-control logic running, and many boards default the fans high or to maximum as a failsafe. Loud at the BIOS screen, quiet at the desktop is normal behavior, not a fault.&lt;/p>
&lt;p>&lt;strong>When the card is genuinely at its limit.&lt;/strong> If a monitoring tool shows the hotspot or memory-junction sensor high while the fans scream, the controller is doing its job and your problem is &lt;a href="https://techfuelhq.com/articles/gpu-overheating-2026/">cooling, not control&lt;/a> — repaste, airflow, or dust, covered in that guide. Everything below assumes the temperatures are unremarkable while the fans are not.&lt;/p>
&lt;h2 id="the-fix-order">The fix order&lt;/h2>
&lt;h3 id="1-reboot-once-properly">1. Reboot once, properly&lt;/h3>
&lt;p>A full shutdown and cold boot clears a one-off controller glitch and re-runs the driver&amp;rsquo;s fan initialization. If the fans come back under control and it never recurs, stop here. If it recurs, the reboot was a clue, not a fix — keep going.&lt;/p>
&lt;h3 id="2-find-the-fight-between-fan-control-programs">2. Find the fight between fan-control programs&lt;/h3>
&lt;p>Count everything on the machine that can touch GPU fans: MSI Afterburner, the card vendor&amp;rsquo;s utility (Armoury Crate, Adrenalin&amp;rsquo;s tuning tab, iCUE, and friends), and motherboard suites. Two controllers arguing over one card routinely ends with a curve pinned at an extreme. Pick &lt;strong>one&lt;/strong> owner, disable GPU fan control everywhere else, then set that one program&amp;rsquo;s curve back to its default profile. While you are in there, check for a forgotten manual override — a fixed-speed toggle left at 100% behaves exactly like this and survives reboots.&lt;/p>
&lt;h3 id="3-reset-the-curve-itself">3. Reset the curve itself&lt;/h3>
&lt;p>If the single remaining controller still pins the fans, its stored curve or the card&amp;rsquo;s fan table may be corrupt. Reset the utility to defaults (or uninstall it and let the driver&amp;rsquo;s automatic control take over). On cards with a dual-BIOS switch, confirm it did not get bumped to the performance position, which runs a deliberately aggressive curve on some models.&lt;/p>
&lt;h3 id="4-rule-out-the-driver-crash-fallback">4. Rule out the driver-crash fallback&lt;/h3>
&lt;p>A hung or crashed driver can leave the card with no one steering — and the failsafe is full speed, the same as before boot. If the pinning started after a driver update, or fans max out mid-session while the screen stutters or recovers, do a clean reinstall with DDU in Safe Mode per the &lt;a href="https://techfuelhq.com/articles/gpu-driver-crash-fix-2026/">GPU driver crash guide&lt;/a>. Install the previous stable driver if the newest one is when the trouble began.&lt;/p>
&lt;h3 id="5-check-what-the-sensors-are-actually-reporting">5. Check what the sensors are actually reporting&lt;/h3>
&lt;p>Open a monitor that shows every GPU sensor, not just the core. A controller reacting to a hotspot or memory sensor you were not watching is case &amp;ldquo;working as designed&amp;rdquo; from the first section. But a sensor reading that is obviously wrong — a temperature pinned at an impossible value while the others sit normal — means the controller is acting on bad input, which on most cards is a warranty conversation rather than a settings fix.&lt;/p>
&lt;h3 id="6-suspect-the-fan-that-reads-zero">6. Suspect the fan that reads zero&lt;/h3>
&lt;p>If one fan reports 0 RPM under load while its neighbors run flat out, the controller may be compensating for a fan it believes has died — and the dead fan (or its tachometer wire) is the real fault. Confirm visually under load: a fan commanded to spin that stands still is the answer. Individual replacement fans exist for most current cards, and swapping one is far cheaper than living at 100%.&lt;/p>
&lt;h2 id="after-it-is-fixed">After it is fixed&lt;/h2>
&lt;p>Set the curve somewhere sane and quiet — the diagram above is the shape to aim for: silent below the zero-RPM threshold, smooth ramp through the middle, maximum held in reserve for genuine trouble. If what pushed you here was noise generally, an &lt;a href="https://techfuelhq.com/articles/how-to-undervolt-gpu-2026/">undervolt&lt;/a> cuts the heat the curve responds to, and if the sound that remains is an electronic whine rather than airflow, that is &lt;a href="https://techfuelhq.com/articles/coil-whine-2026/">coil whine&lt;/a> — a different animal with its own page. And if your problem is the opposite one, read &lt;a href="https://techfuelhq.com/articles/gpu-fans-not-spinning-2026/">GPU fans not spinning&lt;/a> instead.&lt;/p></description></item><item><title>MXFP4 vs Q4_K_M: Why 21B Beats 14B on an RTX 5080</title><link>https://techfuelhq.com/articles/mxfp4-vs-q4km-rtx-5080/</link><pubDate>Thu, 13 Aug 2026 09:05:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/articles/mxfp4-vs-q4km-rtx-5080/</guid><description>&lt;p>The strangest row in &lt;a href="https://techfuelhq.com/data/rtx-5080-llm-throughput/">our RTX 5080 throughput dataset&lt;/a> is the one where the biggest model is not the slowest. gpt-oss 20B — 20.9B parameters as ollama reports it — decodes at &lt;strong>187–190 tokens per second&lt;/strong>. Qwen 2.5 14B, six billion parameters smaller, manages &lt;strong>94–97&lt;/strong>. The &amp;ldquo;bigger&amp;rdquo; model is twice as fast, and it lands within a few percent of the dense &lt;strong>7B&lt;/strong>. None of that is a fluke, and the explanation is worth having because it changes which models you should even shortlist on a 16GB card.&lt;/p>
&lt;img src="https://techfuelhq.com/images/articles/mxfp4-vs-q4km-decode-chart.svg" alt="Bar chart of measured ollama decode speed on an RTX 5080: Llama 3.2 3B at 298-313 tokens per second, gpt-oss 20B MXFP4 at 187-190, Qwen 2.5 7B at 177-180, Qwen 2.5 14B Q4_K_M at 94-97" width="1200" height="640" loading="eager" fetchpriority="high" decoding="async" style="display:block;margin:1.5rem auto;max-width:100%;height:auto;border:1px solid #1e1e3a;border-radius:8px;" />
&lt;h2 id="the-numbers-and-where-they-come-from">The numbers, and where they come from&lt;/h2>
&lt;p>Everything below is from our own bench: ollama 0.32.1 on a retail RTX 5080 (driver 610.88), medians of three fresh-prefill runs per cell, model digests pinned, with a nonce prepended each rep so the prompt cache cannot fake the prefill numbers. The full matrix, method, and raw CSV are on the &lt;a href="https://techfuelhq.com/data/rtx-5080-llm-throughput/">dataset page&lt;/a>.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Model&lt;/th>
&lt;th scope="col">Params&lt;/th>
&lt;th scope="col">Quant&lt;/th>
&lt;th scope="col">Decode tok/s&lt;/th>
&lt;th scope="col">Resident VRAM&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Llama 3.2 3B&lt;/td>
&lt;td>3.2B&lt;/td>
&lt;td>Q4_K_M&lt;/td>
&lt;td>298–313&lt;/td>
&lt;td>~5.4GiB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>gpt-oss 20B&lt;/strong>&lt;/td>
&lt;td>&lt;strong>20.9B&lt;/strong>&lt;/td>
&lt;td>&lt;strong>MXFP4&lt;/strong>&lt;/td>
&lt;td>&lt;strong>187–190&lt;/strong>&lt;/td>
&lt;td>&lt;strong>~13.7–14.0GiB&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Qwen 2.5 7B&lt;/td>
&lt;td>7.6B&lt;/td>
&lt;td>Q4_K_M&lt;/td>
&lt;td>177–180&lt;/td>
&lt;td>~6.0–6.9GiB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Qwen 2.5 14B&lt;/td>
&lt;td>14.8B&lt;/td>
&lt;td>Q4_K_M&lt;/td>
&lt;td>94–97&lt;/td>
&lt;td>~10.6–12.8GiB&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;h2 id="decode-is-a-memory-race-and-only-active-bytes-run-it">Decode is a memory race, and only active bytes run it&lt;/h2>
&lt;p>Generating a token means streaming the model&amp;rsquo;s weights through the GPU once. Do that a hundred times a second and the limiting factor is not compute — it is how fast VRAM can feed the cores. The RTX 5080&amp;rsquo;s memory bus moves about 960 GB/s. So the ceiling is simple division: bandwidth over bytes-touched-per-token.&lt;/p>
&lt;p>Run it for the dense 14B. Q4_K_M stores roughly 4.5–4.8 bits per weight, so 14.8B parameters is about &lt;strong>8.5–8.9GB that every single token must read&lt;/strong>. 960 ÷ 8.7 ≈ 110 tokens per second as the theoretical ceiling — and the measured 94–97 is about 90% of that. The arithmetic and the measurement agree, which is how you know the model is bandwidth-bound.&lt;/p>
&lt;p>Now gpt-oss 20B. It is a mixture-of-experts model: per OpenAI&amp;rsquo;s model card, 21B total parameters but only about &lt;strong>3.6B active per token&lt;/strong>, with the expert weights shipped natively in MXFP4 — 4-bit floating point with shared scale factors, the OCP microscaling format. The 21B has to &lt;em>fit&lt;/em> in VRAM (hence the ~14GiB resident), but each token only &lt;em>streams&lt;/em> the active slice. A few gigabytes per token instead of nine. That is the whole trick, and it is why the 21B model decodes like a 7B — because per token, it approximately is one.&lt;/p>
&lt;p>Total parameters decide whether a model fits. &lt;strong>Active bytes decide how fast it runs.&lt;/strong> Those are different questions, and the spec sheets only advertise the first.&lt;/p>
&lt;h2 id="what-context-length-actually-costs">What context length actually costs&lt;/h2>
&lt;p>The other quietly useful result: at prompts of ~500 and ~1,700 tokens, decode speed was flat between num_ctx 4096 and 16384 for every model — within about 1%. The 16k configurations cost VRAM (the KV cache has to live somewhere) but not speed at these lengths. If you have been keeping context small to protect tokens per second, at normal prompt sizes you are paying a real capacity price for an imaginary speed benefit. Push into genuinely long prompts and attention will eventually take its cut — but that boundary is much further out than the folk wisdom says.&lt;/p>
&lt;p>Prefill tells the same story from the other side: it is compute-bound and parallel, and gpt-oss chewed through prompts at 9,000–10,500 tokens per second, roughly double the dense 14B there too.&lt;/p>
&lt;h2 id="what-to-shortlist-on-a-16gb-card">What to shortlist on a 16GB card&lt;/h2>
&lt;p>If you want the strongest model that still &lt;em>feels&lt;/em> instant on this class of hardware, the measured answer is the MoE: gpt-oss 20B gives 14B-and-up class capability at dense-7B interactive speed, for about 14GiB of resident VRAM. The dense 14B is the choice when a specific dense model&amp;rsquo;s quality on your task justifies half the speed. And the 3B remains the bulk-work option — 300 tokens per second is a different kind of tool.&lt;/p>
&lt;p>Where your GPU lands if it is not a 5080: the &lt;a href="https://techfuelhq.com/articles/local-llm-by-gpu-vram-2026/">local LLM by GPU VRAM guide&lt;/a> maps models to cards, the &lt;a href="https://techfuelhq.com/tools/llm-speed-calculator/">LLM speed calculator&lt;/a> estimates decode from bandwidth and quant, and the &lt;a href="https://techfuelhq.com/tools/llm-vram-calculator/">VRAM calculator&lt;/a> does the fit math. What running this card 24/7 costs in electricity is measured in the &lt;a href="https://techfuelhq.com/articles/rtx-5080-perf-per-watt-ai-24-7-2026/">5080 perf-per-watt piece&lt;/a>.&lt;/p>
&lt;p>The dataset behind every number here is CC BY 4.0 — take it: &lt;a href="https://techfuelhq.com/data/rtx-5080-llm-throughput/">/data/rtx-5080-llm-throughput/&lt;/a>.&lt;/p></description></item><item><title>Coil Whine Database: Per-Model Community Census (GPU, PSU, AIO)</title><link>https://techfuelhq.com/data/coil-whine-database/</link><pubDate>Wed, 12 Aug 2026 00:00:00 -0500</pubDate><author>LK Wood IV</author><guid>https://techfuelhq.com/data/coil-whine-database/</guid><description>&lt;p>By &lt;a href="https://techfuelhq.com/author/lk-wood-iv/">LK Wood IV&lt;/a> · Published 2026-08-12 · ~5 min read · St. Louis County, MO&lt;/p>
&lt;h2 id="the-short-version">The short version&lt;/h2>
&lt;p>Coil whine is one of the most-asked PC noise questions with the least data behind
it. As of an August 2026 check, no per-model coil whine database existed anywhere —
community knowledge lives in scattered forum threads, plus one lab analysis
(&lt;a href="https://www.hwcooling.net/" rel="noopener">hwcooling.net&lt;/a>) that measured a 30-card batch once and
stopped. Meanwhile &amp;ldquo;coil whine&amp;rdquo; draws about 2,900 searches a month and &amp;ldquo;gpu coil
whine&amp;rdquo; another 1,000 (Google Ads exact match, checked 2026-08-12). This page opens
the census that should exist: owner reports of GPUs, PSUs, and AIO pumps on an
anchored 0-4 severity scale, published as per-model distributions.&lt;/p>
&lt;p>The raw data, schema, and intake all live in the open repository:
&lt;strong>&lt;a href="https://github.com/iBlessi/coil-whine-db" rel="noopener">github.com/iBlessi/coil-whine-db&lt;/a>&lt;/strong> (CC BY 4.0).&lt;/p>
&lt;h2 id="why-distributions-never-verdicts">Why distributions, never verdicts&lt;/h2>
&lt;p>The defining fact about coil whine is the design constraint for the whole dataset:
&lt;strong>it varies unit to unit.&lt;/strong> The same GPU model ships silent units and screaming
units, because the outcome depends on which inductors a particular board received,
how they were potted, the PSU feeding them, and the load pattern — not on the model
name. A review unit that stays quiet proves nothing about the unit you will receive,
and one loud unit on a forum proves nothing about the model.&lt;/p>
&lt;p>So the honest per-model answer is never &amp;ldquo;the RTX 4090 whines&amp;rdquo; or &amp;ldquo;it doesn&amp;rsquo;t.&amp;rdquo; It is
a distribution: out of &lt;em>n&lt;/em> reported units, this share was inaudible, this share was
audible at the desk, this share screamed even at idle. That is what this database
publishes — odds, never verdicts.&lt;/p>
&lt;h2 id="the-schema">The schema&lt;/h2>
&lt;p>One row = one physical unit an owner listened to. Full machine-readable definitions
live in &lt;a href="https://github.com/iBlessi/coil-whine-db/blob/main/schema.json" rel="noopener">&lt;code>schema.json&lt;/code>&lt;/a>.&lt;/p>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col">Field&lt;/th>
&lt;th scope="col">Required&lt;/th>
&lt;th scope="col">What it records&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>component_type&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>&lt;code>gpu&lt;/code>, &lt;code>psu&lt;/code>, or &lt;code>aio-pump&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>brand&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>As printed on the box — ASUS, Corsair, Arctic&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>model&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>Model line, specific enough to group units — &amp;ldquo;ROG Strix RTX 4090&amp;rdquo;, &amp;ldquo;RM850x (2021)&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>exact_sku&lt;/code>&lt;/td>
&lt;td>no&lt;/td>
&lt;td>Exact manufacturer SKU when known&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>purchase_year&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>Year this unit was bought&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>severity&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>0–4 on the anchored scale below&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>load_context&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>Where the score was observed: &lt;code>idle&lt;/code>, &lt;code>gaming&lt;/code>, &lt;code>menu-uncapped-fps&lt;/code>, &lt;code>furmark&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>psu_used&lt;/code>&lt;/td>
&lt;td>no&lt;/td>
&lt;td>For GPU reports: the PSU in the system — whine sometimes moves with it&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>fps_cap_changes_it&lt;/code>&lt;/td>
&lt;td>no&lt;/td>
&lt;td>Whether capping FPS audibly changes it — &lt;code>true&lt;/code> / &lt;code>false&lt;/code> / untested&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>notes&lt;/code>&lt;/td>
&lt;td>no&lt;/td>
&lt;td>Free text, max 280 characters&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>submitted_date&lt;/code>&lt;/td>
&lt;td>yes&lt;/td>
&lt;td>ISO date of the report&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;h3 id="the-severity-scale-anchored">The severity scale (anchored)&lt;/h3>
&lt;div class="table-wrap">
&lt;table>
&lt;thead>
&lt;tr>
&lt;th scope="col" style="text-align: right">Severity&lt;/th>
&lt;th scope="col">Anchor&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: right">&lt;strong>0&lt;/strong>&lt;/td>
&lt;td>Inaudible in a quiet room&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: right">&lt;strong>1&lt;/strong>&lt;/td>
&lt;td>Audible with an ear at the case&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: right">&lt;strong>2&lt;/strong>&lt;/td>
&lt;td>Audible at the desk under load&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: right">&lt;strong>3&lt;/strong>&lt;/td>
&lt;td>Audible across the room under load&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: right">&lt;strong>4&lt;/strong>&lt;/td>
&lt;td>Audible even at idle&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p>Score the unit at its loudest normal state. The anchors are fixed on purpose:
changing them would make old and new rows incomparable, so any future anchor change
bumps the dataset&amp;rsquo;s major version instead of quietly redefining the numbers.&lt;/p>
&lt;h2 id="how-to-submit-a-unit">How to submit a unit&lt;/h2>
&lt;p>One report = one physical unit you own or owned, judged by your own ears — not a
model you read about. &lt;strong>Severity-0 reports (&amp;ldquo;mine is silent&amp;rdquo;) are the most valuable
rows in the census&lt;/strong>, because they are the half of the distribution that never shows
up in forum threads.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>No git knowledge needed&lt;/strong> — fill in the
&lt;a href="https://github.com/iBlessi/coil-whine-db/issues/new?template=submission.yml" rel="noopener">coil whine report issue form&lt;/a>.
It mirrors the schema field-for-field; a maintainer transcribes accepted reports
into the CSV, with &lt;code>submitted_date&lt;/code> taken from the issue&amp;rsquo;s creation date.&lt;/li>
&lt;li>&lt;strong>The CSV path&lt;/strong> — add one row to
&lt;a href="https://github.com/iBlessi/coil-whine-db/blob/main/data/submissions.csv" rel="noopener">&lt;code>data/submissions.csv&lt;/code>&lt;/a>
following the schema, and open a pull request. A stdlib validator runs on every
PR and blocks malformed rows.&lt;/li>
&lt;/ol>
&lt;p>Every submission passes two layers before it lands: the mechanical schema check, and
a maintainer review for outlier and troll patterns — duplicate-account bursts filing
the same model at the same severity, impossible combinations like a purchase year
before the model existed, and rows that summarize other people&amp;rsquo;s threads instead of
a unit the submitter heard. The full acceptance rules are in
&lt;a href="https://github.com/iBlessi/coil-whine-db/blob/main/CONTRIBUTING.md" rel="noopener">CONTRIBUTING.md&lt;/a>.&lt;/p>
&lt;h2 id="what-publishes-as-the-census-grows">What publishes as the census grows&lt;/h2>
&lt;p>The activation floor, stated verbatim: &lt;strong>per-model n + severity distribution once a
model has &amp;gt;=5 reports.&lt;/strong> Below that floor a model is listed as &lt;em>collecting&lt;/em>, with no
numbers attached. As models cross the floor, their distributions render on this page
— n first, then the share of reports at each severity level, always with the sample
size in the same breath as the percentages.&lt;/p>
&lt;p>The census opened at &lt;strong>0 rows&lt;/strong> by design — a dataset about unit-to-unit variance
cannot be seeded from published reviews, because each review describes a single unit
that is not ours to report. Every row is a real owner reporting a real unit.&lt;/p>
&lt;p>&lt;strong>Current count: n=1.&lt;/strong> &lt;a href="https://github.com/iBlessi/coil-whine-db/issues/1" rel="noopener">Submission #1&lt;/a>
is the maintainer&amp;rsquo;s own ASUS ROG Astral RTX 5080 OC — severity 1, audible only in
uncapped game menus, silenced by any frame cap. It is the same physical card behind
the &lt;a href="https://techfuelhq.com/data/gpu/rog-astral-rtx-5080-oc-2026-06-09/">Astral 5080 bench dataset&lt;/a>, so its
provenance is already public. One report proves the pipeline, not a distribution:
the ROG Astral RTX 5080 OC is listed as &lt;em>collecting&lt;/em> until it reaches n=5.&lt;/p>
&lt;h2 id="the-honesty-rules">The honesty rules&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>No verdicts below n = 5.&lt;/strong> A model with three angry reports is &lt;em>collecting&lt;/em>, not
&amp;ldquo;a whiner.&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Self-selection bias is named, not hidden.&lt;/strong> People annoyed by a noise go looking
for a place to report it; people with silent units mostly don&amp;rsquo;t. Annoyed owners
over-report and silent units under-report, so every published whine percentage is
a &lt;strong>ceiling&lt;/strong>, not an unbiased estimate. The severity-0 row exists to shrink that
bias, not to pretend it away.&lt;/li>
&lt;li>&lt;strong>Anchors never drift.&lt;/strong> The 0–4 scale above is frozen; a change would be a new
major version, and old rows would be marked as scored on the old scale.&lt;/li>
&lt;/ul>
&lt;h2 id="use-the-data-cc-by-40">Use the data (CC BY 4.0)&lt;/h2>
&lt;p>The live dataset is one file:
&lt;a href="https://raw.githubusercontent.com/iBlessi/coil-whine-db/main/data/submissions.csv" rel="noopener">&lt;code>data/submissions.csv&lt;/code>&lt;/a>
— one row per reported unit, in the schema order above. License: Creative Commons
Attribution 4.0. Attribute as &amp;ldquo;TechFuelHQ Community Coil Whine Census&amp;rdquo; linking to
this page.&lt;/p>
&lt;p>If the noise is bothering you today, the diagnosis and mitigation walkthrough is the
&lt;a href="https://techfuelhq.com/articles/coil-whine-2026/">coil whine guide: is it normal, and where is it coming from?&lt;/a>
— and a brand-new buzz paired with crashes belongs in the
&lt;a href="https://techfuelhq.com/articles/psu-failure-symptoms-2026/">PSU failure symptoms guide&lt;/a> rather than a
census form. If capping FPS quiets your card and you want the deeper fix, the
&lt;a href="https://techfuelhq.com/articles/gpu-undervolt-settings-database/">GPU undervolt settings database&lt;/a> is the
companion dataset.&lt;/p>
&lt;h2 id="change-log">Change log&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>0.1.0 (2026-08-12)&lt;/strong> — schema, anchored severity scale, intake (issue form + PR
path), validator, and the empty census opened: 0 rows, no seeded data.&lt;/li>
&lt;li>&lt;strong>0.1.1 (2026-08-13)&lt;/strong> — first accepted report: the maintainer&amp;rsquo;s own Astral
RTX 5080 OC via the issue-form flow (issue #1 -&amp;gt; validated row). n=1; every
model remains below the n&amp;gt;=5 distribution floor.&lt;/li>
&lt;/ul></description></item></channel></rss>