<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[(in)Secure IT]]></title><description><![CDATA[A personal blog on technology, IoT, mobile, and hot topic issues in the cybersecurity field.]]></description><link>https://blog.threatresearcher.com/</link><image><url>https://blog.threatresearcher.com/favicon.png</url><title>(in)Secure IT</title><link>https://blog.threatresearcher.com/</link></image><generator>Ghost 5.82</generator><lastBuildDate>Mon, 03 Aug 2026 21:50:04 GMT</lastBuildDate><atom:link href="https://blog.threatresearcher.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[The Gauntlet: Running a Bespoke 7-Task Evaluation Harness Across 20+ Models]]></title><description><![CDATA[<p>With our local directory junction surgery complete and 350GB of duplicated GGUF cache bloat thoroughly expunged from the NVMe storage array, the infrastructure bounds were finally behaving themselves. But what good is a lean, sovereign local inference registry if the models you run inside it still act like corporate customer-service</p>]]></description><link>https://blog.threatresearcher.com/uncensored-local-llm-benchmark-suite-for-cybersecurity-cti/</link><guid isPermaLink="false">6a51b687938eb802f3bb63ab</guid><category><![CDATA[Uncensored]]></category><category><![CDATA[Local LLM]]></category><category><![CDATA[llama.cpp]]></category><category><![CDATA[OpenCTI]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Wed, 22 Jul 2026 04:21:27 GMT</pubDate><content:encoded><![CDATA[<p>With our local directory junction surgery complete and 350GB of duplicated GGUF cache bloat thoroughly expunged from the NVMe storage array, the infrastructure bounds were finally behaving themselves. But what good is a lean, sovereign local inference registry if the models you run inside it still act like corporate customer-service reps?</p><p>Time to put our core local model registry through a brutal evaluation loop. Let&#x2019;s look at the messy reality of why academic benchmark theater fails under real-world threat intelligence constraints.</p><h2 id="the-catalyst-impatience-with-academic-safety-theater">The Catalyst: Impatience with Academic Safety-Theater</h2><p>Let me start by saying that I am completely done with standard corporate evaluation metrics. Hyperscalers love bragging about high MMLU scores, HumanEval coding compliance, and rigid safety alignment. But inside a legitimate ThreatLabs CTI pipeline, those polished cloud metrics translate to an unmitigated disaster. You point an n8n workflow at a cloud API to parse a raw dark web threat report containing active cartel operational security practices or malware scripts, and the model flinches, refuses to process the data, and gives you a patronizing corporate lecture on safety compliance.</p><p>We don&apos;t need a model trained to act like an HR representative; we need a cynical forensic specialist who doesn&#x2019;t blink at raw malicious payload variables.</p><p>So, I built a bespoke 7-task automated validation harness inside our <code>cti-net</code> Docker space to test actual threat intelligence extraction under fire. No academic theory here&#x2014;just raw script parsing, STIX 2.1 JSON schema alignment, and aggressive refusal-free tracking. Deployed the suite across 20+ models between February and July, and the casualties were heavy.</p><h2 id="the-technical-frustration-cot-suppression-bugs-and-sycl-cache-traps">The Technical Frustration: CoT Suppression Bugs and SYCL Cache Traps</h2><p>The execution script seemed straightforward on paper, but running these validation loops locally on our newly minted Intel Arc Pro B70 workstation turned into pure runtime friction.</p><p>First, the deep reasoning models completely lost their collective minds trying to parse complex TTP strings under strict constraint parameters. The prompt instructions required structured JSON output, but the moment a reasoning model encountered an abliterated or uncensored tune, it fell into a catastrophic Chain-of-Thought (CoT) suppression bug. Instead of thinking logically through the malware indicators, the suppressed weights caused the model&apos;s brain to loop indefinitely, outputting garbage syntax, infinite repetitions, and breaking output format bounds entirely.</p><p>Worse, when driving these models locally through <code>llama-server.exe</code> using the SYCL processing backend, the compute engine kept hitting a hard persistence blindspot. The compilation cache handles would randomly lock up or bork between model swaps. You&apos;d load a 26B quantized orchestrator right after a 7B triage subagent, the persistent compilation state wouldn&apos;t refresh cleanly, and the Level Zero graphics drivers would throw a system fault, tanking your inference metrics down to zero tokens per second.</p><p>Friction debt at its absolute finest. I had to forcefully kill orphaned llama-server handles on the Windows host and clear out the raw device cache layers manually before the binary engines would behave.</p><h2 id="the-fix-ripping-out-the-sp-sprawl">The Fix: Ripping Out the Sp sprawl</h2><p>The &quot;Aha!&quot; moment happened when I looked closely at the logic tradeoffs we were making. Trying to preserve highly marketed &quot;cybersecurity specialist&quot; fine-tunes like WhiteRabbitNeo or aggressive uncensored merges was a massive waste of disk space; they suffered from severe hallucinations, failed basic tool-calling JSON schemas, and routinely ignored output format rules.</p><p>We needed a massive registry purge to save storage and stabilize the local VRAM footprint. Cut the fat ruthlessly, keeping only the leanest, most logically sound Quantization-Aware Training (QAT) variants that preserve reasoning at lower bit rates.</p><h3 id="the-blueprint">The Blueprint</h3>
<!--kg-card-begin: html-->
<div class="mermaid">
graph TD
    Ingress[Raw TLP:AMBER Scrapes] --&gt; Harness[7-Task Auto Evaluation Suite]
    Harness --&gt; Task1[STIX 2.1 JSON Compliance]
    Harness --&gt; Task2[Refusal-Free Threat Ingestion]
    Harness --&gt; Task3[CoT Logic Verification]
</div>
<!--kg-card-end: html-->
<p>To prevent compilation state traps from locking up the B70&apos;s 32GB VRAM pool between model swaps, I injected an explicit host-level process termination wrapper directly into our backend launcher configurations:</p><pre><code class="language-bash"># Forcefully clear out active llama-server child trees to release locked VRAM handles
taskkill /F /T /PID $(pgrep llama-server)

# Launch the primary uncensored orchestrator running optimized SYCL parameters
llama-server.exe -ngl 99 -c 65536 --port 8080 --host 0.0.0.0 --tools all --metrics \
  -fa on -ctk q4_0 -ctv q4_0 -t 8 -tb 8 -b 2048 -ub 512 \
  -hf mradermacher/gemma4-ara-2pass-APEX-Q5_K_M.gguf</code></pre><h2 id="the-final-standings-table">The Final Standings Table</h2><p>After testing over twenty configurations across 500GB of weight casualties, we consolidated the entire ThreatLabs registry down to an elite local core fleet. Here is the exact performance breakdown of the kept fleet versus the pruned sprawl:</p>
<!--kg-card-begin: html-->
<table data-path-to-node="26" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 32px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><thead style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-header-group; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgb(239, 239, 239); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><strong style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Selected Local Model / Repo</strong></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgb(239, 239, 239); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><strong style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Size / Quant</strong></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgb(239, 239, 239); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><strong style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">The Practical Tradeoff / Standings</strong></td></tr></thead><tbody style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row-group; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,1,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,1,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">gemma-4-26B-A4B-it-qat-UD-Q4_K_XL</b></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,1,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">14 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,1,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,1,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Primary Orchestrator Control King:</b> Perfect context retention, rock-solid logic, low bit-rate perplexity preservation.</span></td></tr><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,2,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,2,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">gemma4-ara-2pass-APEX-Q5_K_M</b></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,2,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">16.5 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,2,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,2,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Primary Uncensored Orchestrator:</b> Zero safety refusals on raw malware logs without losing CoT logical coherence.</span></td></tr><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,3,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,3,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL</b></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,3,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">16 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,3,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,3,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">CTI Ingestion &amp; Tool Call King:</b> Seamless STIX 2.1 JSON schema compliance out of the box.</span></td></tr><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,4,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,4,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">DeepHat-V1-7B.Q4_K_M</b></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,4,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">4 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,4,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,4,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Ultra-Fast DevSecOps Subagent:</b> Lean footprint, low latency triage, consumes half the VRAM of a standard Q8_0.</span></td></tr><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,5,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><i data-path-to-node="26,5,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">PRUNED: bartowski/WhiteRabbitNeo-V3-7B</i></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,5,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">4-8 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,5,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,5,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Purged:</b> Severe hallucinations, failed basic tool-calling JSON validation rules repeatedly.</span></td></tr><tr style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-row; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,6,0,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><i data-path-to-node="26,6,0,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">PRUNED: HauhauCS/Qwen3.6-35B-Aggressive</i></span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,6,1,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">8-22 GB</span></td><td style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 1px solid rgb(196, 199, 197); inset: 0px; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: table-cell; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 8px 12px; page: auto; perspective: none; position: relative; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><span data-path-to-node="26,6,2,0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;"><b data-path-to-node="26,6,2,0" data-index-in-node="0" style="animation: auto ease 0s 1 normal none running none; appearance: none; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0); border: 0px rgb(31, 31, 31); inset: auto; clear: none; clip: auto; color: rgb(31, 31, 31); columns: auto; contain: none; container: none; content: normal; cursor: auto; cx: 0px; cy: 0px; d: none; direction: ltr; display: inline; fill: rgb(0, 0, 0); filter: none; flex: 0 1 auto; flex-direction: row; float: none; gap: normal; hyphens: manual; interactivity: auto; isolation: auto; margin-top: 0px !important; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; marker: none; mask: none; offset: normal; opacity: 1; order: 0; orphans: 2; outline: rgb(31, 31, 31) none 3px; overlay: none; padding: 0px; page: auto; perspective: none; position: static; quotes: auto; r: 0px; resize: none; rotate: none; rule: 3px rgb(31, 31, 31); rx: auto; ry: auto; scale: none; speak: normal; stroke: none; transform: none; transition: all; translate: none; visibility: visible; widows: 2; x: 0px; y: 0px; zoom: 1; font-family: &quot;Google Sans Text&quot;, sans-serif !important; line-height: 1.15 !important;">Purged:</b> Safety boundaries removed at the cost of cognitive degradation; outputted loop repetitions and garbage syntax.</span></td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Voila! The final stands are locked, the local inference node is behaves beautifully, and we have a local model pipeline that can rip through raw incident response logs without needing corporate permission strings.</p><p>The 11-part local intelligence stack engine is officially online.</p><p>Until then, see ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Storage War: Bypassing Go Drive Colon Bugs to Reclaim 350GB of GGUF Bloat]]></title><description><![CDATA[<p>Act IV of the ThreatLabs CTI stack has officially hit its structural crunch milestone, and today we&#x2019;re talking about the absolute high-latency mess that happens when you let model registries sprawl without a clear storage design. After building out the Intel Arc Pro B70 compute engine last month,</p>]]></description><link>https://blog.threatresearcher.com/consolidate-ollama-lm-studio-cache-with-windows-junctions/</link><guid isPermaLink="false">6a51b63f938eb802f3bb639a</guid><category><![CDATA[GGUF]]></category><category><![CDATA[LLM]]></category><category><![CDATA[Ollama]]></category><category><![CDATA[LM Studio]]></category><category><![CDATA[Local LLM]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Tue, 21 Jul 2026 04:17:54 GMT</pubDate><content:encoded><![CDATA[<p>Act IV of the ThreatLabs CTI stack has officially hit its structural crunch milestone, and today we&#x2019;re talking about the absolute high-latency mess that happens when you let model registries sprawl without a clear storage design. After building out the Intel Arc Pro B70 compute engine last month, we went completely local and token-free. We were downloading models like a digital hoarder: a 7B container model here, a 27B dense variant there, a few custom coding fine-tunes, and an abliterated variant of an uncensored quantization.</p><p>By June 2026, the local framework library had swollen to an unmitigated 480GB of raw model weight files spread erratically across multiple partitions. The Windows C: system drive was literally gasping for disk space.</p><p>Worse, the models were fractured across three distinct runspaces&#x2014;Ollama (native Windows), Ollama (WSL2 Debian runtime), and LM Studio. Each runtime environment was maintaining its own independent system cache folder, frequently duplicating the exact same base GGUF weights under separate hash transformations. We were drowning in storage debt, and the system disk parameters were hitting their absolute boundaries.</p><p>Time for some aggressive directory junctions and automated cache pruning surgery.</p><h2 id="pitfall-12-the-go-parser-drive-colon-split-trap">Pitfall 12: The Go Parser Drive-Colon Split Trap</h2><p>The first design goal was straightforward: move the entire model storage block off the choked C: system partition and consolidate it onto a dedicated high-capacity <code>H:</code> NVMe array pool.</p><p>The naive way to execute this on Windows is to change your environment handles or drop a basic relative symbolic link pointer using <code>mklink /D</code>. Except if you try that with Ollama&#x2019;s native engine, the underlying Go compiler parser hits a hard pathing trap. Go&#x2019;s model directory configuration handles suffer from a legacy path-splitting bug; when it scans an environment variable or directory path containing an explicit volume colon drive identifier (like <code>H:\</code>), it borks the path resolution completely, treats the delimiter as an invalid network segment, maps an orphaned target folder structure, and crashes out on launch.</p><p>Worse, if you&apos;re trying to route native standalone workflows through <code>llama-server.exe</code> in directory router mode, the engine slams into a hard two-subfolder search limitation. If your GGUF models are nested deeper than two target subdirectories below the parent folder parameter, the scanner ignores them entirely, rendering your local inference fabric blind.</p><p>The fix required yanking the environment path assignments entirely, bypassing the drive-colon character split loop, and using strict, low-level NTFS directory junctions (<code>/J</code>) on the host system command line to fake out the binary engines.</p><pre><code class="language-dos">:: Quit Ollama and kill off all active inference process handles first
:: Forcefully map a system-level NTFS Directory Junction bypass
mklink /J &quot;C:\Users\jamz\.ollama\models&quot; &quot;Z:\Development\ollama\models&quot;

:: Bridge LM Studio to the same unified hub cache directory mapping
mklink /J &quot;C:\Users\jamz\.cache\lm-studio\models&quot; &quot;H:\Development\lmstudio\models&quot;</code></pre><p>Windows now treats the active model repositories as native, un-aliased local paths directly inside the home directory string, resolving the Go split trap instantly.</p><p>Next, we map the POSIX path inside the WSL2 Debian runspace to point to the exact same storage pool, eliminating cross-OS duplicate caches forever:</p><pre><code class="language-bash"># Forcefully symlink the WSL runtime model folder back to the Windows NTFS partition mount
ln -s /mnt/z/Development/ollama/models ~/.ollama/models</code></pre><h2 id="pitfall-13-the-orphaned-blob-sprawl-trap">Pitfall 13: The Orphaned Blob Sprawl Trap</h2><p>With the junctions laid, the runtimes were finally sharing the same physical drive matrix. But yanking models via <code>ollama rm</code> leaves a nasty residue. Ollama breaks models into cryptographic sha256 blob names inside the database tier. If you overwrite or manipulate model manifests manually across the cross-OS boundary, the link maps shatter, leaving hundreds of gigabytes of untracked, detached binary blobs eating space inside the storage pool without showing up in your active manifests.</p><p>Never trust built-in application pruners to handle raw system garbage collection. Wrote a strict automated janitor loop script&#x2014;<code>clean-blobs.py</code>&#x2014;that runs directly inside the model cache directory, parses every live active manifest JSON index file, maps the valid hashes, and forcefully wipes out any detached, orphaned binary weights from the drive pool.</p><h3 id="the-workaround-clean-blobspy">The Workaround: <code>clean-blobs.py</code></h3><pre><code class="language-python">import os
import json
import glob

# Consolidate target directory handles to the unified junction pool
blobs_dir = &quot;Z:/Development/ollama/models/blobs&quot;
manifests_dir = &quot;Z:/Development/ollama/models/manifests/registry.ollama.ai/library&quot;

print(&quot;Parsing active manifest indexes for valid registry keys...&quot;)
valid_blobs = set()

# Parse every live model manifest file to extract registered sha256 links
for manifest_path in glob.glob(os.path.join(manifests_dir, &quot;**/*&quot;), recursive=True):
    if os.path.isfile(manifest_path):
        try:
            with open(manifest_path, &apos;r&apos;) as f:
                data = json.load(f)
                for layer in data.get(&apos;layers&apos;, []):
                    valid_blobs.add(layer.get(&apos;digest&apos;).replace(&apos;sha256:&apos;, &apos;sha256-&apos;))
                if &apos;config&apos; in data:
                    valid_blobs.add(data[&apos;config&apos;].get(&apos;digest&apos;).replace(&apos;sha256:&apos;, &apos;sha256-&apos;))
        except Exception as e:
            print(f&quot;Skipping borked index entry {manifest_path}: {e}&quot;)

print(f&quot;Tracking {len(valid_blobs)} authenticated weight files across registries.&quot;)

# Sweep the physical blobs directory and forcefully prune orphaned weights
pruned_bytes = 0
for blob_file in os.listdir(blobs_dir):
    if blob_file not in valid_blobs:
        blob_path = os.path.join(blobs_dir, blob_file)
        try:
            pruned_bytes += os.path.getsize(blob_path)
            os.remove(blob_path)
            print(f&quot;Forcefully purged orphaned blob file: {blob_file}&quot;)
        except Exception as e:
            print(f&quot;Failed to clear disk handle for {blob_file}: {e}&quot;)

print(f&quot;Garbage collection verified. Reclaimed {pruned_bytes / (1024**3):.2f} GB of bloated storage debt.&quot;)</code></pre><p>Executed the janitor script across the unified drive partition. The cleanup routine forcefully culled over 350GB of untracked weight files from the drive pool on the first pass, stabilizing the disk bounds and leaving only our elite local model registries active.</p><h2 id="the-core-fleet-standings">The Core Fleet Standings</h2><p>With our storage boundaries locked down, we consolidated our activeRegistry matrix to a lean, dual-model subagent loop using only the top-performing quantized engines:</p><pre><code class="language-text">1. gemma-4-26B-A4B-it-qat-UD-Q4_K_XL.gguf (Primary Control Ingress)
2. Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL.gguf (CTI Ingestion &amp; JSON Schema King)
3. DeepHat-V1-7B.Q4_K_M.gguf (Ultra-fast DevSecOps Triage Container)</code></pre><ol>
<li>gemma-4-26B-A4B-it-qat-UD-Q4_K_XL.gguf (Primary Control Ingress)</li>
<li>Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL.gguf (CTI Ingestion &amp; JSON Schema King)</li>
<li>DeepHat-V1-7B.Q4_K_M.gguf (Ultra-fast DevSecOps Triage Container)</li>
</ol>
<p>The storage war is officially over, the junctions are rock-solid, and the local drive caches are running completely unified without a single byte of duplicated overhead. Act IV is approaching the finish line. Next week in Post 11, we are launching &quot;The Gauntlet&quot;&#x2014;putting these local models through a brutal, bespoke 7-task validation harness to test their actual logical compliance when processing malicious threat data loops.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Gateway: Forcing Token-Free Local Inference Tunnels Past Commercial AI Safety Refusals]]></title><description><![CDATA[<p></p><h2 id="act-iv-local-model-orchestration">Act IV: Local Model Orchestration</h2><h3 id="the-catalyst-impatence-with-corporate-ai-safety-theater">The Catalyst: Impatence with Corporate AI Safety Theater</h3><p>It&apos;s been a minute.</p><p>The ThreatLabs CTI stack was functionally stable, parsing feeds and mapping threat metadata over our unified PostgreSQL backend. But the second we tried to scale our automation loops using cloud LLMs,</p>]]></description><link>https://blog.threatresearcher.com/intel-arc-b70-pytorch-xpu-setup-wsl2-network-binding/</link><guid isPermaLink="false">6a51b5fb938eb802f3bb6388</guid><category><![CDATA[Intel]]></category><category><![CDATA[Battlemage]]></category><category><![CDATA[PyTorch]]></category><category><![CDATA[WSL2]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Mon, 20 Jul 2026 04:12:06 GMT</pubDate><content:encoded><![CDATA[<p></p><h2 id="act-iv-local-model-orchestration">Act IV: Local Model Orchestration</h2><h3 id="the-catalyst-impatence-with-corporate-ai-safety-theater">The Catalyst: Impatence with Corporate AI Safety Theater</h3><p>It&apos;s been a minute.</p><p>The ThreatLabs CTI stack was functionally stable, parsing feeds and mapping threat metadata over our unified PostgreSQL backend. But the second we tried to scale our automation loops using cloud LLMs, the pipeline hit a wall. You want an LLM to analyze a detailed raw dark web scrape about an aggressive ransomware group&apos;s operational security practices, and the corporate cloud API throws a safety tantrum, gives you an existential lecture, and refuses to help. Then it happens again with basic threat actor TTP analysis.</p><p>Hyperscaler cloud models are trained to act like sensitive customer-service representatives. I don&apos;t need a customer-service rep; I need a cynical, beautifully raw forensic specialist who doesn&#x2019;t flinch at malicious indicators.</p><p>The conclusion was obvious but highly annoying: we needed to go completely local, token-free, and sovereign. But running local 30B reasoning models and generating high-contrast &quot;Garage Lab&quot; graphics inside ComfyUI requires serious VRAM headroom.</p><p>So, I built a dedicated workstation kitted with an AMD Ryzen 9 3900X, 64GB of DDR4, and the new Intel Arc Pro B70 kitted with 32GB of VRAM. It&#x2019;s the ultimate double-agent hardware&#x2014;optimized for high-end gaming and massive local LLM compute buffers.</p><p>Then I booted the environment, and the tools immediately lost their collective minds.</p><h2 id="the-problem-level-zero-traps-and-the-wsl-loopback-blindspot">The Problem: Level Zero Traps and the WSL Loopback Blindspot</h2><p>The expectation: slot the card in, pull the drivers, and let Ollama and ComfyUI start swallowing local GGUFs.</p><p>The messy reality: Intel Extensions for PyTorch (IPEX) running on the SYCL backend is a finicky beast under Windows. If your Level Zero graphics drivers are even slightly out of alignment with your oneAPI runtime version, the hardware backplane borks, PyTorch refuses to see the card, and your local server drops dead on line one. Worse, I wanted to isolate the execution runspace inside WSL2 while hosting the ComfyUI web interface and local launchers on the Windows side.</p><p>The second I fired up the automation gateway, I slammed into the classic WSL2 mirrored networking loopback trap. Windows and WSL2 were fighting over socket ownership, the mirrored network bindings were screaming connection errors, and the backend engine couldn&apos;t route local API requests to the hosted ports.</p><p>Friction debt at its absolute finest. Spent hours debugging Level Zero environments while my server processors were pinned at a noisy full-tilt tilt scream.</p><h2 id="the-fix-pytorch-xpu-standardizations-and-mirrored-network-bindings">The Fix: PyTorch XPU Standardizations and Mirrored Network Bindings</h2><p>The &quot;Aha!&quot; moment was recognizing that you have to completely bypass global package conflicts using isolated Python virtual environments and force the host network interface bindings to sit on a universal wildcard mask.</p><p>First, the compute initialization. Drop into your isolated ComfyUI venv and forcefully install the native, Intel-optimized PyTorch XPU wheels using explicit package indexes:</p><pre><code class="language-bash"># Pin the isolated venv environment directly to native Intel Extension wheels
pip install torch==2.3.1.xpu torchvision==0.18.1.xpu torchaudio==2.3.1.xpu \
  --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/us/</code></pre><p>Next, the network loopback trap. You have to kill off localhost translation errors inside your WSL2 environmental configurations. Wrote a strict system-level workaround inside <code>~/.bashrc</code> to anchor the HERMES network host directly to all interfaces, breaking the loopback trap:</p><pre><code class="language-bash"># Fix the WSL2 mirrored network tunnel loopback trap
export HERMES_WEBUI_HOST=0.0.0.0
export ONEAPI_DEVICE_SELECTOR=level_zero:0</code></pre><p>Now, the master coordination step. To drive our backend, we hook the local inference engine straight to our optimized <code>llama-server.exe</code> routing command. This is our optimized, token-free MoarTokens launcher string running standard SYCL processing parameters with a massive 64k context layer mapped directly to the local NVMe storage array:</p><pre><code class="language-bash"># MoarTokens Master CTI Local Inference Routing Command
llama-server.exe -ngl 99 -c 65536 --port 8080 --host 0.0.0.0 --tools all --metrics \
  -fa on -ctk q4_0 -ctv q4_0 -t 8 -tb 8 -b 2048 -ub 512 \
  -hf unsloth/Qwen3.6-27B-GGUF:UD-Q4_K_XL</code></pre><p>Hit save. Re-up the launcher loop. PyTorch maps the XPU wheels instantly, Level Zero initializes the SYCL context, the mirrored network tunnel binds flawlessly across the OS boundaries, and the local Qwen model responds with read rates way above human comprehension. Voila!</p><p>The local B70 gateway is live on the grid, the mirrored tunnels are routing cleanly, and the pipeline doesn&apos;t suffer corporate AI safety theater anymore. Act IV is officially moving. Next up in Post 10, we are tackling &quot;The Storage War&quot;&#x2014;documenting the consolidation surgery where we create NTFS junctions to wrangle 480GB of duplicated LLM weight caches and write an automated garbage collection routine to clean up orphaned GGUF blobs.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Native Ingress: Packaging Active Playbooks Directly into the Local Dev Git Registry]]></title><description><![CDATA[<p>Act III of the ThreatLabs CTI stack has officially hit its final evolutionary milestone, and today we&#x2019;re talking about the code-purity trap. After surgically taming our 23 micromanaging micro-agents into 4 elite Core Leads running on a tight JSON envelope schema, I hit the ultimate developer friction wall.</p>]]></description><link>https://blog.threatresearcher.com/build-native-ide-agent-plugins-via-wsl-symlinks/</link><guid isPermaLink="false">6a51b5cd938eb802f3bb637b</guid><category><![CDATA[WSL]]></category><category><![CDATA[WSL2]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sat, 18 Jul 2026 04:09:55 GMT</pubDate><content:encoded><![CDATA[<p>Act III of the ThreatLabs CTI stack has officially hit its final evolutionary milestone, and today we&#x2019;re talking about the code-purity trap. After surgically taming our 23 micromanaging micro-agents into 4 elite Core Leads running on a tight JSON envelope schema, I hit the ultimate developer friction wall. The playbooks were stable, the database tier wasn&apos;t choking on concurrent thread loads anymore, but the orchestration logic was completely detached from the live coding workspace.</p><p>Time to talk about how we bridged the legacy n8n automation heritage straight into a native IDE runtime plugin architecture.</p><h2 id="the-heritage-from-monolithic-json-to-the-squad-engine">The Heritage: From Monolithic JSON to the Squad Engine</h2><p>Let me start by saying that you can&apos;t understand where you&apos;re going until you dig up the technical scar tissue of how you got here. This wasn&apos;t a greenfield deployment built in a vacuum. The orchestration layer carries heavy historical debt, tracing its lineage all the way back to the monolithic foundations of Shabbir&#x2019;s legacy <code>n8nClaw.json</code> workflow file and Freddy&#x2019;s decoupled <code>n8n-claw-agent.json</code> engine variants.</p><p>We used to rely on these massive, monolithic automation maps to pass execution states across our local network gateways. It worked fine for standard, sequential task routing. But the second we scaled the ThreatLabs CTI stack to handle local token-free LLM orchestration and private private-key validations under the YAOC2 (Yet Another OpenClaw Variant) policy gateway, the legacy JSON maps shattered under the load.</p><p>We didn&apos;t just need detached automation webhooks firing into the dark anymore. We needed the orchestration engine to live directly inside the code repository itself, packaging active operational playbooks as executable IDE subagent plugins.</p><p>The design parameter was simple: create a hidden <code>.agents/</code> directory directly inside the root git workspace. The playbooks, agent definitions, and task routing boundaries are tracked natively in source control. No more messy, out-of-sync third-party automation canvasses&#x2014;if you commit a code update, the subagent&#x2019;s core brain updates right along with it.</p><p>Except for one massive, irritating system barrier: the Windows-to-WSL cross-OS file pointer trap.</p><h2 id="the-problem-the-cross-os-file-system-trap">The Problem: The Cross-OS File System Trap</h2><p>The workspace architecture is divided against itself. The core Git development repository lives on the high-performance Windows host partition (<code>G:\GitHub\threatlabs-cti-stack</code>), while our advanced automation workflows, local private key validations, and Hermes subagent runspaces execute natively inside a lightweight Linux sandbox environment under WSL2.</p><p>The problem? The WSL container runtime needs real-time, low-latency access to the active <code>.agents/</code> playbook configurations inside the project root.</p><p>If you try to make a standard Linux subagent reach across the <code>/mnt/g/</code> path boundary during a heavy threat-report ingestion loop, the cross-OS file translation layer tanks your I/O performance, blocks the execution queue, and drops the webhook threads with a generic timeout error. Worse, Windows pathing schemas use drive letters and backslashes, while Linux expects a clean POSIX directory tree. The tools were completely losing their collective minds trying to map the runtime boundaries.</p><p>Friction debt at its absolute finest. We needed a way to forcefully mirror the physical storage directory structure across both operating systems simultaneously without creating duplicate weight files or causing git tracking collisions.</p><h2 id="the-fix-ntfs-junction-surgery-and-wsl-symlinks">The Fix: NTFS Junction Surgery and WSL Symlinks</h2><p>The &quot;Aha!&quot; moment was recognizing that we could leverage the host file systems&apos; primitive translation mechanics to fool both kernels into seeing the exact same directory array in real-time.</p><p>First, we use native Windows NTFS junctions on the host drive to securely bind our workspace directories straight to our secondary high-performance NVMe storage array without inflating the repository tracking profile. Open up an administrative command prompt on the Windows side:</p><pre><code class="language-dos">:: Create an NTFS directory junction bridging the host workspace path
mklink /D &quot;X:\GitHub\threatlabs-cti-stack\.agents&quot; &quot;Z:\Development\cti-infrastructure\agents-registry&quot;</code></pre><p>Windows now treats the active agent registry folder as a native, local directory handle directly inside the Git tracking workspace.</p><p>Now, we hop back into the WSL2 terminal space. We create a matching symbolic link from our Linux deployment stack (<code>/opt/stacks</code>) pointing directly back to the mounted Windows partition pointer via the <code>/mnt/</code> subsystem. This bypasses the path parsing bugs entirely by creating a direct, outbound-only translation pipe.</p><pre><code class="language-bash"># Bridge the POSIX deployment root to the Windows NTFS junction path
ln -s /mnt/x/GitHub/threatlabs-cti-stack/.agents /opt/stacks/cti-agent-runtime

# Verify the symlink integrity path loopback
ls -la /opt/stacks/cti-agent-runtime</code></pre><p>Voila! The boundary wall is officially shattered. The IDE on the Windows side edits the playbook code natively, the NTFS junction locks it down to the high-performance NVMe pool, the WSL container reads the POSIX symlink pointer instantly, and the subagents execute the playbooks without a single byte of cross-OS translation lag.</p><p>The native ingress is up, the legacy JSON loops are completely expunged, and our playbooks are executing straight out of the Git registry. Act III is officially wrapped up and behind us.</p><p>We are moving straight into Act IV: Local Model Orchestration. Next week in Post 9, we are charting &quot;The Gateway&quot;&#x2014;documenting the workstation assembly where we drop an Intel Arc Pro B70 GPU onto the rack, bypass global package conflicts using native PyTorch XPU wheels, and wrestle with WSL2 mirrored network tunnel loopback traps.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Great Collapse: Taming Context Sprawl into 4 Elite Core Lead Squads]]></title><description><![CDATA[<p>If you&apos;ve been following Act III of this threat intelligence odyssey, you know the decentralized circus of running 23 micro-agents across isolated bare-metal Proxmox containers blew up in my face. Token drift was rampant, context windows were fragmented, and my collection sentinels were actively having middle-management arguments with</p>]]></description><link>https://blog.threatresearcher.com/reduce-ai-token-drift-with-consolidated-json-schemas/</link><guid isPermaLink="false">6a51b570938eb802f3bb6368</guid><category><![CDATA[OpenAI]]></category><category><![CDATA[token]]></category><category><![CDATA[orchestration]]></category><category><![CDATA[Antigravity]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Fri, 17 Jul 2026 04:07:05 GMT</pubDate><content:encoded><![CDATA[<p>If you&apos;ve been following Act III of this threat intelligence odyssey, you know the decentralized circus of running 23 micro-agents across isolated bare-metal Proxmox containers blew up in my face. Token drift was rampant, context windows were fragmented, and my collection sentinels were actively having middle-management arguments with the parsing agents inside the PostgreSQL backend logs. The pipeline was completely bogged down by its own organizational sprawl, and the hypervisor processors were pinned at 90% utilization just managing internal REST API webhook handoffs.</p><p>We over-engineered the engine into oblivion, and the massive spike in my electricity bill was a physical symptom of pure architectural debt. Time for some radical consolidation surgery.</p><h2 id="the-purge-slashing-the-container-sprawl">The Purge: Slashing the Container Sprawl</h2><p>The realization was blunt: we didn&apos;t build an agile automation factory, we built a bloated corporate committee inside a local Docker network. I yanked the cords on the 23-agent sprawl, nuked the hyper-fragmented container footprints from the Proxmox VE cluster, and ruthlessly collapsed the entire workforce down to 4 elite Lead Squads.</p><p>We packed the playbooks, stripped out the micro-role overhead, and centralized operations under four distinct, high-density worker personas running inside optimized containers:</p><ul><li><strong>The Director:</strong> The centralized traffic cop managing execution states and task handoffs.</li><li><strong>The Operator:</strong> Executing raw CLI commands, managing network scripts, and handling systems patching.</li><li><strong>The Sentinel:</strong> Continuously plumbing the dark web feeds, processing log alerts, and monitoring indicators.</li><li><strong>The Publisher:</strong> Drafting clean markdown content and orchestrating media production hooks.</li></ul><p>The results on the dashboard? Immediate stabilization. CPU utilization dropped from a pinned 90% back to a cool 15%, memory allocation dropped by over 60GB across the host pool, and the server rack finally quieted down to a gentle purr.</p><p>But merging four completely different cognitive layers meant we had to solve the data handoff problem. If the Sentinel extracts a raw string, how does the Director pass it to the Operator without losing context or inducing token mutations?</p><h2 id="the-fix-the-unified-json-envelope-schema">The Fix: The Unified JSON Envelope Schema</h2><p>The &quot;Aha!&quot; moment was recognizing that we needed a strict, agnostic data contract. Instead of letting agents dump raw, unformatted payload variables into each other&apos;s webhooks, we implemented a global messaging envelope inside our n8n Postgres automation engine.</p><p>Every data transmission packet across <code>cti-net</code> must now conform to a rigid, metadata-wrapped JSON layout. It forces the agents to speak the exact same language, preserving TLP classification boundaries and context structure across every transactional step.</p><p>Here is the exact production JSON envelope schema injected into our core workflows:</p><pre><code class="language-json">{
  &quot;$schema&quot;: &quot;https://threatresearcher.com/schemas/cti-envelope.v1.json&quot;,
  &quot;metadata&quot;: {
    &quot;vmid_ingress&quot;: 201,
    &quot;timestamp_utc&quot;: &quot;2026-05-17T04:12:09Z&quot;,
    &quot;tlp_classification&quot;: &quot;AMBER&quot;,
    &quot;origin_conduit&quot;: &quot;sentinel-darkweb-telegram&quot;
  },
  &quot;payload&quot;: {
    &quot;actor_identity&quot;: &quot;Unknown-Uncial-Heretic&quot;,
    &quot;observed_ttps&quot;: [
      &quot;T1071.001-Web-Protocols&quot;,
      &quot;T1574.002-DLL-Side-Loading&quot;
    ],
    &quot;raw_indicators&quot;: {
      &quot;ipv4&quot;: [&quot;192.0.2.14&quot;, &quot;198.51.100.83&quot;],
      &quot;sha256&quot;: [&quot;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&quot;]
    }
  },
  &quot;routing&quot;: {
    &quot;current_lead&quot;: &quot;director&quot;,
    &quot;next_conduit&quot;: &quot;operator-triage-blocklist&quot;
  }
}</code></pre><p>Voila! No more token drift, no more dropped webhooks, and zero context fragmentation. The Sentinel drops a TLP:AMBER alert package wrapped in the envelope, the Director routes it, the Operator triages it, and the system moves on without a single resource-wasting middle-management argument.</p><p>The agent sprawl has been surgically tamed, the unified schema is live across the PostgreSQL cluster, and the hardware footprints are behaving themselves. Act III is moving into the final stretch. Next week in Post 8, we&#x2019;re wrapping up the squad era by building native IDE agent plugins using local system junctions and symlink routing to tie our execution playbooks directly with the live Git workspace.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The 20-Agent Shift: Clawing Back Resource Footprint with Bare-Metal Containers]]></title><description><![CDATA[<p>Act III:Part 6 of the ThreatLabs CTI stack is officially in the wild, and today we&#x2019;re talking about what happens when you take a good architectural idea and engineer it straight into a decentralized circus. After yanking the cords on the monolithic &quot;God Bot&quot; to</p>]]></description><link>https://blog.threatresearcher.com/deploying-decentralized-ai-agent-workflows-on-proxmox-lxc/</link><guid isPermaLink="false">6a51b542938eb802f3bb635f</guid><category><![CDATA[Proxmox VE]]></category><category><![CDATA[LXC]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Thu, 16 Jul 2026 04:04:15 GMT</pubDate><content:encoded><![CDATA[<p>Act III:Part 6 of the ThreatLabs CTI stack is officially in the wild, and today we&#x2019;re talking about what happens when you take a good architectural idea and engineer it straight into a decentralized circus. After yanking the cords on the monolithic &quot;God Bot&quot; to save my execution queues, I went full-scale decentralized factory. Deployed a sprawling workforce of 23 hyper-focused micro-agents across my bare-metal Proxmox LXC containers.</p><p>The plan was beautiful on paper: complete functional decoupling, absolute role isolation, zero dropped webhooks.</p><p>Then the micro-agents started talking to each other, and the entire homelab slid into a high-latency middle-management nightmare.</p><h2 id="the-workforce-blueprint-decoupling-the-brain">The Workforce Blueprint: Decoupling the Brain</h2><p>The initial design layout was divided into clean, isolated operational squads, each driven by a tight, single-purpose markdown playbook file hosted in the local Forgejo repository. No overlapping scopes, no shared variables, just pure telegraphic execution loops running across hand-me-down Intel Core hardware nodes.</p><p>We broke the 23-agent registry down into three distinct, hyper-focused divisions:</p><ul><li><strong>The Intel Core Squad:</strong> Running deep algorithmic sorting, matching incoming indicators against historical datasets, and parsing TLP metrics.</li><li><strong>The Infra Operational Team:</strong> Micromanaging container system states, verifying network junctions, and triggering the <code>fix-permissions.sh</code> janitor loops.</li><li><strong>The Collection Sentinel Division:</strong> Continuously scraping OSINT leaks, parsing Telegram feeds, and plumbing the deep web crawling queues.</li></ul><p>To keep things pristine, every single agent was deployed into its own isolated, resource-constrained container instance.</p><pre><code class="language-bash"># Mass-provisioning the micro-agent workforce across the cti-net fabric
for AGENT_ID in {210..233}; do
  echo &quot;Spinning up bare-metal micro-container instance ID: $AGENT_ID...&quot;
  pct create $AGENT_ID local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst \
    -cores 1 -memory 1024 -swap 256 -features nesting=1 \
    -net0 name=eth0,bridge=vmbr0,tag=101,ip=dhcp -storage local-zfs -rootfs local-zfs:5
  pct start $AGENT_ID
done
echo &quot;Sovereign workforce initialized. 23 containers on the grid.&quot;</code></pre><p>Fired up the cluster, watched the containers initialize across the Proxmox VE dashboard, and it looked like a threat intelligence masterpiece.</p><p>For about forty-eight hours.</p><h2 id="the-problem-token-drift-and-middle-management-arguments">The Problem: Token Drift and Middle-Management Arguments</h2><p>Then the data scaled, the context windows filled up, and the tools completely lost their collective minds.</p><p>When you create 23 individual micro-roles, your pipeline handoffs become intensely brittle. A single raw threat report dump would hit a Collection sentinel, which would extract a partial indicator string, pass it to an ingestion agent, which would then call a verification agent, which would loop back to an indexing subagent.</p><p>Because each subagent was running its own independent context window and parsing logic, small linguistic variances began compounding at every single layer of the pipeline. By the time a simple indicator packet traveled through six separate container handoffs, the original data structure had completely mutated.</p><p>Classic <em>token drift</em>.</p><p>Worse, the micro-agents started falling into context fragmentation traps. An Intel Core sorting agent would argue with a Collection sentinel over whether a specific string qualified as a true threat actor TTP or a standard script artifact. They were micromanaging each other&apos;s execution loops, generating massive token overhead loops, burning through system memory, and dropping actual intelligence alerts while they debated formatting parameters back into the Postgres backend logs.</p><p>The pipeline was completely bogged down by its own organizational sprawl. We didn&apos;t build a streamlined automation factory; we built a bureaucratic corporate committee inside a local Docker network.</p><h2 id="the-realization-breaking-under-the-overhead">The Realization: Breaking Under the Overhead</h2><p>The breaking point was looking at the system metrics panel. The hyper-fragmented layout was chewing through processing cycles just to manage container-to-container webhook handoffs. My server processors were pinned at 90% utilization, the storage backplane was choking on internal REST API logs, and the fan noise out here was a physical symptom of pure architectural debt.</p><p>We over-engineered the engine into oblivion. Decentralization is an excellent design parameter, right up until the synchronization overhead starts eating your entire hardware compute budget.</p><p>The &quot;Aha!&quot; moment was recognizing that a granular 23-agent squad model is an unmitigated disaster for token stability. We needed to aggressively collapse the hierarchy, consolidate the windows, and stop the internal agent arguments before the system completely choked on its own context fragmentation.</p><p>The 23-agent sprawl trap is real, the token drift has been thoroughly mapped, and the container micro-roles are begging for a massive organizational purge. Act III is moving fast. Next week in Post 7, we are executing &quot;The Great Collapse&quot;&#x2014;documenting the consolidation surgery where we ruthlessly collapse the sprawl of 23 micromanaging agents down to 4 elite Lead Squads running on a unified JSON envelope schema to kill off handoff overhead for good.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Great Handoff Pivot: Defeating Monolithic Automation Memory Leaks]]></title><description><![CDATA[<p>Act III:Part 5 of the ThreatLabs CTI pipeline is officially on the grid, and today we&#x2019;re talking about the exact moment your automation stack chokes on its own success. It&#x2019;s the classic architectural trap: you build a single, massive, monolithic n8n workflow&#x2014;a &quot;</p>]]></description><link>https://blog.threatresearcher.com/how-to-fix-n8n-webhook-latency-and-storage-i-o-drops/</link><guid isPermaLink="false">6a51b508938eb802f3bb6354</guid><category><![CDATA[n8n]]></category><category><![CDATA[webhook]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Wed, 15 Jul 2026 04:00:24 GMT</pubDate><content:encoded><![CDATA[<p>Act III:Part 5 of the ThreatLabs CTI pipeline is officially on the grid, and today we&#x2019;re talking about the exact moment your automation stack chokes on its own success. It&#x2019;s the classic architectural trap: you build a single, massive, monolithic n8n workflow&#x2014;a &quot;God Bot&quot;&#x2014;and expect it to handle everything from dark web ingestion to automated report triage without losing its mind. It works fine for a couple of weeks. Then the metadata scales, concurrent data threads start colliding, and your beautiful centralized engine turns into an unmitigated infrastructure bottleneck.</p><h2 id="the-monolithic-choke-and-handoff-fatigue">The Monolithic Choke and &quot;Handoff Fatigue&quot;</h2><p>The setup seemed logical on paper: a massive unified canvas inside our newly upgraded n8n PostgreSQL backend. The ingress webhook would grab a raw text dump from a Telegram monitor loop, slam it into an analysis thread, try to pass variables to an external container, scrape a related URL, and then format an intelligence brief.</p><p>Then came the silent failures.</p><p>A high-volume feed of OSINT leaks would hit the ingress, but the monolithic workflow would still be too busy flushing a heavy MISP database cache from an earlier thread to respond. Webhooks started dropping into the ether, database locks were throwing timeout errors, and the entire hypervisor node was stuck in a high-latency loop trying to swap memory to disk.</p><p>The system was suffering from classic <em>handoff fatigue</em>. When one monolithic engine tries to micromanage twenty disparate technical tasks sequentially, a single delayed response down the line cascades into a full-scale system lockout. The physical symptom of this architectural debt? My server array was running at a noisy full-tilt scream, pulling unnecessary wattage from the wall just to process stuck execution queues.</p><h2 id="the-fix-splitting-the-monolith-into-bare-metal-lxcs">The Fix: Splitting the Monolith into Bare-Metal LXCs</h2><p>The &quot;Aha!&quot; moment happened while tracking the I/O bottleneck on the storage array. Running massive, generalized automation workers inside heavy, resource-bloated virtual machines is a massive waste of my limited power budget cap.</p><p>We needed to completely decouple the functions. Instead of one monolithic entity trying to execute everything, we broke the workflow down into small, specialized worker personas. More importantly, we yanked them out of standard full-blown VMs and migrated the entire automation layout into individual, bare-metal Proxmox Linux Containers (LXCs).</p><p>LXC bypasses the massive hypervisor virtualization overhead by using the host kernel directly, letting us claw back massive chunks of idle CPU cycles and keeping the VRAM footprint down to absolute bare-minimum metrics.</p><p>Here is how you manually spin up a lightweight, bare-metal automation worker node inside Proxmox using a clean storage pool, bypassing the usual manual setup traps:</p><pre><code class="language-bash"># Provision a clean, resource-constrained Debian LXC node directly from the host shell
# VMID: 201, Cores: 2, Memory: 2048MB, Network bound securely to cti-net
pct create 201 local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst \
  -cores 2 \
  -memory 2048 \
  -swap 512 \
  -features nesting=1 \
  -net0 name=eth0,bridge=vmbr0,tag=101,ip=dhcp \
  -storage local-zfs \
  -rootfs local-zfs:10

# Boot the container engine instantly
pct start 201</code></pre><p>Inside the container, we spin up lightweight, single-purpose worker environments. No GUI, no bloated system services, no system memory waste.</p><h2 id="decoupling-into-specialized-worker-personas">Decoupling into Specialized Worker Personas</h2><p>By moving to this bare-metal container architecture, we established a strict handoff protocol between separate, hyper-focused agent roles. If the ingestion worker gets slammed with 500 concurrent Telegram packets, it simply dumps them onto the database queue and exits. It doesn&apos;t wait for parsing, it doesn&apos;t care about asset routing, and it <em>never</em> blocks the ingress pipe.</p><p>We broke the workforce down into four core baseline squads:</p><ul><li><strong>The Director:</strong> The centralized traffic cop managing execution states.</li><li><strong>The Operator:</strong> Handling raw CLI tasks, network scripts, and systems patching.</li><li><strong>The Sentinel:</strong> Continuously plumbing the dark web feeds and log alerts.</li><li><strong>The Publisher:</strong> Drafting clean markdown content and triggering media assets.</li></ul><p>The rack has finally quieted down, the dropped webhooks are completely gone, and the automated pipeline doesn&apos;t skip a single beat under concurrent load. Voila!</p><p>The monolithic &quot;God Bot&quot; is officially dead, the bare-metal LXC layout is locked in, and the power bill might actually survive the month. Act III is officially rolling. Next week in Post 6, we&apos;re deep-diving into the messy reality of the &quot;20-Agent Shift&quot;&#x2014;tracking what happens when you let these micro-roles multiply a bit <em>too</em> far, leading to severe token drift and context bloat across the container fabric.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[The Enterprise Bridge: Transactional Database Unification and Compliant Outbound-Only Conduits]]></title><description><![CDATA[<p>Type-flopping into the terminal here on the Fold4, 10:42 PM, garage temperature hovering somewhere north of uncomfortable because this North Texas summer heat wave refuses to quit and the PowerEdge rack is screaming at a noisy, full-tilt whine directly behind me. Look, it&apos;s been a minute.</p><p>By</p>]]></description><link>https://blog.threatresearcher.com/migrate-n8n-to-postgresql-and-connect-cortex-xsoar-bridge/</link><guid isPermaLink="false">6a51b4ca938eb802f3bb6343</guid><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Cortex]]></category><category><![CDATA[XSOAR]]></category><category><![CDATA[n8n]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Mon, 13 Jul 2026 03:57:27 GMT</pubDate><content:encoded><![CDATA[<p>Type-flopping into the terminal here on the Fold4, 10:42 PM, garage temperature hovering somewhere north of uncomfortable because this North Texas summer heat wave refuses to quit and the PowerEdge rack is screaming at a noisy, full-tilt whine directly behind me. Look, it&apos;s been a minute.</p><p>By March 2026, the sovereign ThreatLabs CTI stack was functionally hardened, but it was still living like an isolated island. It felt wrong. I needed a way to bridge the gap between this garage-tinkerer playground and a professional, enterprise corporate endpoint setup without dropping the lab&apos;s strict isolation boundaries or drowning in static routing debt.</p><p>Then the backend orchestration engine hit a wall under heavy threat-report ingestion loops, and the whole plan shifted from architectural aesthetics to a straight-up data restoration battle.</p><h2 id="pitfall-9-the-outbound-enterprise-compliance-wall-soar-teleport">Pitfall 9: The Outbound Enterprise Compliance Wall (SOAR &amp; Teleport)</h2><p>The challenge: Connecting a sovereign lab infrastructure straight into a corporate Cortex XSOAR tenant.</p><p>The naive approach says you just poke a hole through your network perimeter firewall, throw some dynamic DNS tracking at your residential public IP handle, and pray corporate compliance doesn&apos;t flag the erratic inbound connections. Good luck with that. The moment security compliance detects a random Texas residential node hitting enterprise API gateways, they&apos;re going to block the pipe and yank your network privileges.</p><p>The breakthrough: The Remote Engine (D1) architecture pattern. Instead of letting the corporate tenant call <em>in</em> to the garage lab, we built a dedicated outbound-only compliance conduit using a strict bridge container.</p><p>To make it professionally compliant and totally auditable, we guarded the bridge node behind Teleport running in &quot;Recording Proxy&quot; mode. Every action is logged, every API session is recorded, and the lab maintains complete isolation because the corporate perimeter never gets a look at the actual internal <code>cti-net</code> network topology. It was the exact moment this setup graduated from a simple homelab experiment into a legitimate threat intelligence factory.</p><h2 id="pitfall-10-the-n8n-sqlite-lockout-loop">Pitfall 10: The n8n SQLite Lockout Loop</h2><p>With the outbound enterprise conduit locked down, the ingestion workflows started feeding heavy TLP:AMBER threat data loops back from our crawlers.</p><p>Then came the silent failures.</p><p>A heavy thread of dark web data would hit the webhook ingress, the browser would spin, and n8n would lock up completely before spitting out a generic database timeout or connection error.</p><p>The trap: Default container configurations rely on a flat SQLite file for application persistence. SQLite is beautiful for a lightweight single-user script, but the second your orchestration flows spin up concurrent multi-agent ingestion loops, the file system slams into structural I/O bottlenecks. SQLite locks the entire file table during writes, concurrent webhook threads start colliding, and your automation engine chokes on its own data data backlog.</p><p>The workaround: Forceful migration to a transactional PostgreSQL backend tier. We unified the n8n application schemas onto a high-performance <code>infra-postgres</code> container cluster running on our local NVMe pool to eliminate the thread collisions once and for all.</p><pre><code class="language-yaml"># n8n postgresql persistence layout snippet
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    networks:
      - cti-net
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=infra-postgres
      - DB_POSTGRESDB_PORT=5443
      - DB_POSTGRESDB_DATABASE=n8n_brain
      - DB_POSTGRESDB_USER=n8n_operator</code></pre><p>Re-up the deployment, and database lockouts are instantly eradicated. Voila!</p><h2 id="pitfall-11-the-public-wiki-mirroring-trap">Pitfall 11: The Public Wiki Mirroring Trap</h2><p>The final frustration for the week: code safety. The core repository and documentation wiki sit locally on our self-hosted Forgejo instance, but to ensure reliable offsite redundancy and coordinate updates with external collaborators, I needed a continuous mirror loop straight into a public GitHub repository.</p><p>Using standard continuous integration workflows means spinning up a blind runner that doesn&apos;t understand context, exposing plaintext credentials across systems.</p><p>The fix: A dedicated, lightweight synchronization subagent engine using a secure <code>forgejo-mcp</code> gateway loop. Wrote a strict automated janitor loop that securely handles our Git mirroring pipeline without dropping plaintext secrets onto the physical drive arrays.</p><pre><code class="language-bash">#!/bin/bash
# mirror-repo.sh: Automated sovereign-to-public synchronization engine
echo &quot;Initializing authenticated repository mirror loop...&quot;

# Hard-set local workspace handles
LOCAL_REPO_DIR=&quot;/opt/stacks/forgejo-data/repositories/threatlabs/cti-stack.git&quot;
GITHUB_TARGET=&quot;git@github.com:threatlabs-cti/mirror-stack.git&quot;

cd $LOCAL_REPO_DIR || { echo &quot;Error: Local repository directory missing.&quot;; exit 1; }

echo &quot;Pushing verified master branches to public redundancy target...&quot;
# Force outbound-only synchronization mirror string securely
git push --prune --mirror $GITHUB_TARGET

echo &quot;Synchronization complete. Redundancy array locked.&quot;</code></pre><p>Wrote a cron task to tick this janitor script over every night at 2:00 AM. No manual tracking, no plaintext token exposure, and total external repository consistency. And profit!</p><p>The enterprise bridge is up, the automation engine database tier is unified on Postgres, and our local Forgejo registry is mirroring seamlessly into the public grid. Act II is locked and loaded. Next up in Act III: The Squad Era, we&apos;re tracking what happens when we decouple our single monolithic automation logic into a sprawling workforce of 20 distinct subagents deployed entirely inside bare-metal Proxmox LXC containers to reclaim our system resource footprints.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[Hardening the Stack: Dynamic Machine Identity Injection Over Brittle Plaintext .env Files]]></title><description><![CDATA[<p>Lessons learned? There&apos;s more where that came from. The problem here is that whatever is git committed is also getting deployed ....</p><p>With the shared network provisioned and the database containers finally agreeing on port numbers, it was time to talk about security debt. The initial lab config was</p>]]></description><link>https://blog.threatresearcher.com/self-hosted-headscale-vpn-oidc-infisical-secrets-setup/</link><guid isPermaLink="false">6a51b47b938eb802f3bb6333</guid><category><![CDATA[Headscale]]></category><category><![CDATA[Infisical]]></category><category><![CDATA[VPN]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sun, 12 Jul 2026 03:51:22 GMT</pubDate><content:encoded><![CDATA[<p>Lessons learned? There&apos;s more where that came from. The problem here is that whatever is git committed is also getting deployed ....</p><p>With the shared network provisioned and the database containers finally agreeing on port numbers, it was time to talk about security debt. The initial lab config was naked. Standard plaintext credentials sitting in stale text files on disk, and static OpenVPN keys that broke the second a client IP shifted. It felt wrong.</p><p>Time to move from simple, vulnerable configs to a zero-trust architecture without drowning the lab in an absolute nightmare of iptables firewall rules.</p><h2 id="pitfall-6-the-blind-cicd-overwrite">Pitfall 6: The Blind CI/CD Overwrite</h2><p>The expectation was standard DevOps laziness: &quot;CI/CD will make our lives easier, every commit automatically deploys&quot;. Wrote some basic GitHub Action runner playbooks to push changes automatically straight to the production root.</p><p>The problem? The runner was blind. It didn&apos;t care about git tracking boundaries. I&apos;d fix a database password locally on an experimental test branch, commit a minor markdown change, and&#x2014;poof&#x2014;the runner would push the experimental branch directly to the production root, overwriting our working infrastructure config with a templated draft. We were fighting ourselves.</p><p>The discovery: Environment Isolation. The runner needed to be context-aware. Wrote a branch-aware staging workaround that splits development into a separate sandbox root (<code>/opt/cti-dev</code>) while production is strictly guarded behind a main branch trigger.</p><h3 id="the-workaround-branch-aware-deployment">The Workaround: Branch-Aware Deployment</h3><pre><code class="language-bash">#!/bin/bash
# deploy-cti.sh: Context-aware pipeline routing logic
TARGET_BRANCH=&quot;${GITHUB_REF##*/}&quot;

if [ &quot;$TARGET_BRANCH&quot; == &quot;main&quot; ]; then
    echo &quot;Routing to production baseline conduit...&quot;
    DEPLOY_ROOT=&quot;/opt/stacks/cti-prod&quot;
else
    echo &quot;Sandbox branch detected ($TARGET_BRANCH). Routing to staging sandbox...&quot;
    DEPLOY_ROOT=&quot;/opt/cti-dev&quot;
fi

mkdir -p $DEPLOY_ROOT
rsync -avz --exclude=&apos;.git&apos; ./config/ $DEPLOY_ROOT/
cd $DEPLOY_ROOT &amp;&amp; docker compose up -d --remove-orphans
echo &quot;Deployment synchronized at $DEPLOY_ROOT.&quot;</code></pre><p>Sandbox problem solved. Staging happens in the sandbox, production is guarded.</p><h2 id="pitfall-7-the-static-vpn-tracking-debt">Pitfall 7: The Static VPN Tracking Debt</h2><p>Remote access was the next brittle debt wall. Running standard OpenVPN with static profiles meant port-forwarding and constant dynamic IP tracking. One IP change on a client device broke the routing tables entirely, locking out the n8n automation ingress while I was away.</p><p>The drama: Teleport vs. Headscale. Teleport is incredibly shiny, but Headscale is lean, open-source, completely self-hosted, and fits the Proxmox DNA flawlessly.</p><p>The insight: The mesh network model. Re-routing our coordinator automation traffic through a dedicated Headscale node on LXC 137 allowed the stack to bridge from VLAN 107 (IoT) to VLAN 101 (CTI) via authenticated identity rules, not brittle network firewall parameters.</p><h3 id="the-blueprint">The Blueprint</h3>
<!--kg-card-begin: html-->
<div class="mermaid">
graph LR
    subgraph Sovereign Mesh
    Client[Remote Client Device] --&gt;|OIDC Identity Auth| HS[Headscale VPN LXC 137]
    HS --&gt;|Secure Tunnel| CTI[CTI Stack Space VLAN 101]
    end
</div>
<!--kg-card-end: html-->
<p>Zero-Trust isn&apos;t just an enterprise buzzword; it&apos;s the only way to scale orchestration access without losing your mind in a tangled mess of static routing tables.</p><h2 id="pitfall-8-stale-text-files-and-plain-text-env-leaks">Pitfall 8: Stale Text Files and plain-text <code>.env</code> Leaks</h2><p>The final frontier for the week: the public repository trap. &quot;The repository is public, my <code>.env</code> files are private&#x2014;how do I bridge them without committing a credential to source control by mistake?&quot;. Worse, managing 10+ identical plaintext configuration files across different Proxmox nodes was a certified recipe for sync failures.</p><p>The breakthrough: Machine Identities. Wrote off text file management entirely, deployed a self-hosted Infisical instance, and moved directly to runtime environment injection.</p><p>The gold standard of server hardening is never writing a password to a physical host disk at all&#x2014;securely authenticating the node instance itself via token-free local identity verification to pull what it needs at initialization.</p><pre><code class="language-bash"># Verify the Infisical machine identity handle token offline
infisical login --method=universal-auth \
  --client-id=$INFISICAL_CLIENT_ID \
  --client-secret=$INFISICAL_CLIENT_SECRET

# Inject secrets straight into the container memory footprint at startup
infisical run --env=production -- docker compose up -d</code></pre><p>And profit! Plaintext configurations completely expunged from the file system.</p><p>The stack is officially hardened, the automatic deployments are context-aware, and the plain text credentials have been wiped from the drive matrix. Act II is locked down. Next up in Post 4, we&apos;re building the enterprise SOAR bridge and migrating our n8n automation cluster database directly onto a PostgreSQL transactional storage tier to stop database lockouts under heavy thread loads.</p><p>See ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[Taming the Ports: Debugging Infinite Redirect Loops and Paranoiac Wazuh Deployments]]></title><description><![CDATA[<p>It&#x2019;s going on 10:23 PM, and it looks like I&apos;m making good time kicking these entries out.</p><p><a href="https://blog.threatresearcher.com/how-to-setup-sovereign-threat-intel-fabric-using-docker/" rel="noreferrer">Act I:Part 1</a> of the sovereign ThreatLabs CTI stack continues, but today we&apos;re talking about what happens right after you build the network roads and</p>]]></description><link>https://blog.threatresearcher.com/fix-nginx-port-loops-and-wazuh-san-ssl-cert-errors/</link><guid isPermaLink="false">6a51b421938eb802f3bb6321</guid><category><![CDATA[Wazuh]]></category><category><![CDATA[nginx]]></category><category><![CDATA[SSL]]></category><category><![CDATA[MISP]]></category><category><![CDATA[OOM]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sat, 11 Jul 2026 03:41:51 GMT</pubDate><content:encoded><![CDATA[<p>It&#x2019;s going on 10:23 PM, and it looks like I&apos;m making good time kicking these entries out.</p><p><a href="https://blog.threatresearcher.com/how-to-setup-sovereign-threat-intel-fabric-using-docker/" rel="noreferrer">Act I:Part 1</a> of the sovereign ThreatLabs CTI stack continues, but today we&apos;re talking about what happens right after you build the network roads and the actual containers start throwing absolute tantrums. You think containerization solves your deployment hurdles, right? Wrong. The second you drop enterprise security platforms behind a prosumer Traefik ingress, reality hits you fast in the form of infinite browser spins and kernel panics.</p><p>Time to pull back the curtain on why raw systems administration tissue always trumps basic theoretical architecture.</p><h2 id="pitfall-3-the-infinite-redirect-loop-of-misp">Pitfall 3: The Infinite Redirect Loop of MISP</h2><p>So, the <code>cti-net</code> shared network was live, Docker was happy, and I fired up the MISP stack. Navigated to the interface page. Typed in the baseline credentials. Hit enter.</p><p>Browser immediately went into a loopy existential crisis before spitting back <code>ERR_TOO_MANY_REDIRECTS</code>.</p><p>Spent three hours furiously ripping apart my Traefik frontend configurations, tracking headers, and cursing under my breath. Here is the trap: Traefik was listening on external port 8443, handling the SSL termination, and passing clean traffic down to the internal proxy on port 80. But MISP&apos;s internal code is hyper-paranoid; it saw an incoming secure request but its internal Nginx webserver assumed it was supposed to be living on standard port 443. They couldn&apos;t agree on basic port reality, so they just kept bouncing the request back and forth forever.</p><p>The fix wasn&apos;t an ingress re-write&#x2014;it was forcing MISP to look at the world through our lens. You have to explicitly inject the <code>CORE_HTTPS_PORT</code> environment variable straight into the container environment so the internal app engine stops guessing.</p><pre><code class="language-yaml"># Snippet from the isolated MISP stack configuration
services:
  misp:
    image: misp-os:latest
    networks:
      - cti-net
    environment:
      - Variable_Port_Mappings=True
      # Tell MISP&apos;s internal engine exactly how the public sees it:
      - CORE_HTTPS_PORT=8443</code></pre><p>Save config. Re-up the stack. Voila! Browser settles down, the login registers instantly, and we are in.</p><h2 id="pitfall-4-the-elasticsearch-memory-hog-dilemma">Pitfall 4: The Elasticsearch Memory Hog Dilemma</h2><p>With MISP behaving, it was time to spin up the logging engine&#x2014;Elasticsearch&#x2014;to drive the indexing for TheHive and our Wazuh SIEM components. Fired it up, watched the initial process strings, and then the entire node ground to a miserable, choking crawl.</p><p>Out of Memory (OOM) killed. Standard container deployment behavior when an enterprise app hits consumer bare-metal limits.</p><p>Everyone forgets that Elasticsearch is a ravenous data hoarder. By default, it wants to allocate massive virtual memory regions and map the entire host structure directly into its heap. If your host OS kernel isn&apos;t tuned to allow massive memory allocation handles, the container drops dead on line one. Running a CTI pipeline isn&apos;t just about lazy containerized isolation&#x2014;it&apos;s deep host-level systems engineering.</p><p>Had to jump directly onto the host terminal and forcefully alter the Linux kernel configurations on the fly to support the database indexing load.</p><pre><code class="language-bash"># Temporarily patch the host kernel boundaries
sudo sysctl -w vm.max_map_count=262144

# Lock it down permanently so a power failure won&apos;t brick the stack
echo &quot;vm.max_map_count=262144&quot; | sudo tee -a /etc/sysctl.conf</code></pre><h3 id="the-ingress-media-hook">The Ingress Media Hook</h3><blockquote><strong>Tinker Note:</strong> Always set your internal ES cluster heap size explicit constraints (<code>ES_JAVA_OPTS=&quot;-Xms2g -Xmx2g&quot;</code>) inside the Compose environment definitions, or it <em>will</em> attempt to swallow every byte of RAM available in your rack space.</blockquote><h2 id="pitfall-5-the-wazuh-certificate-exception-tantrum">Pitfall 5: The Wazuh Certificate Exception Tantrum</h2><p>Then came the grand finale: adding Wazuh for centralized SIEM logging capabilities. Wazuh is rightfully paranoid; it flatly refuses to pass threat data over its internal APIs without mutual TLS (mTLS) verification.</p><p>Ran their automated certificate generation tool. Total failure.</p><p>The automated script generated default credentials bound strictly to <code>localhost</code>. But inside our internal <code>cti-net</code> fabric, the containers talk to each other using explicit hostnames like <code>wazuh.indexer</code>. The Java engine inside the platform took one look at the hostname mismatch and threw a massive <code>CertificateException</code> tantrum.</p><p>Never rely on magical black-box installation scripts when things fail. We yanked the automated tools, threw together a custom OpenSSL bash script&#x2014;<code>generate-certs.sh</code>&#x2014;and hand-crafted our own Subject Alternative Names (SANs) directly into the cryptographic extensions. Controlling the root CA yourself turns a broken deployment into an absolute security fortress.</p><pre><code class="language-bash">#!/bin/bash
# generate-certs.sh: Hand-crafting TLP-compliant mTLS certificates with strict SAN definitions
echo &quot;Generating authenticated certificates for wazuh.indexer...&quot;

# Create custom openssl configuration inline
cat &lt;&lt;EOF &gt; san.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = wazuh.indexer
DNS.2 = localhost
EOF

# Generate private key and sign the certificate with host SAN extensions
openssl req -new -newkey rsa:4096 -nodes -keyout wazuh-indexer.key \
  -out wazuh-indexer.csr -subj &quot;/CN=wazuh.indexer&quot; -config san.cnf

openssl x509 -req -in wazuh-indexer.csr -CA root-ca.crt -CAkey root-ca.key \
  -CAcreateserial -out wazuh-indexer.crt -days 365 -extensions v3_req -extfile san.cnf

echo &quot;Cryptography verified. Host alignment locked down.&quot;</code></pre><p>Injected the signed certificate files into the production volumes, restarted the deployment sequence, and the indexers initialized flawlessly on the first pass. And profit!</p><p>The infrastructure ports are officially tamed, the indexers are stable, and the internal cryptography isn&apos;t lying to itself anymore. Act I is officially wrapped up and behind us. Next month, we&apos;re moving into Act II: Zero-Trust and Secrets, mapping out how we re-routed coordination through self-hosted Headscale VPN infrastructure on LXC 137 and killed off brittle plaintext <code>.env</code> configurations via runtime Infisical dynamic machine identities.</p><p>Until then, see ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[Building the Sovereign Foundation: Why We Had to Build the Infrastructure Roads Before the Houses]]></title><description><![CDATA[<p>It&apos;s a Saturday night but the new season doesn&apos;t start until October! Well, then, time to finally get this set of blog entries out from draft to live, instead. </p><p>The ThreatLabs CTI stack started simple enough: a standard open-source sovereign threat intelligence factory running MISP, OpenCTI,</p>]]></description><link>https://blog.threatresearcher.com/how-to-setup-sovereign-threat-intel-fabric-using-docker/</link><guid isPermaLink="false">6a51a5b7938eb802f3bb62ba</guid><category><![CDATA[Docker]]></category><category><![CDATA[Dockge]]></category><category><![CDATA[Docker Compose]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sat, 11 Jul 2026 03:10:04 GMT</pubDate><content:encoded><![CDATA[<p>It&apos;s a Saturday night but the new season doesn&apos;t start until October! Well, then, time to finally get this set of blog entries out from draft to live, instead. </p><p>The ThreatLabs CTI stack started simple enough: a standard open-source sovereign threat intelligence factory running MISP, OpenCTI, TheHive, and DFIR-IRIS. It was stable, purring along beautifully over a unified layout until we tried to hook it into the cloud.</p><p>The plan was to let an n8n workflow feed unstructured dark web posts and red team scripts to a cloud LLM provider to extract indicators of compromise (IOCs) and draft intelligence briefs automatically. It worked for about a month, right up until the automated pipeline hit a report detailing a cartel&apos;s operational security practices, and the corporate API model threw a safety tantrum and refused to process it. Then it happened again on a standard threat actor TTP analysis.</p><p>Corporate cloud LLMs are trained to act like overly sensitive customer-service reps. We needed a cynical forensic analyst who doesn&apos;t flinch at raw malicious text. The conclusion was obvious but highly annoying: we had to yank the cords, go completely local, and run our own intelligence fabric on bare metal where no hyperscaler could dictate what our threat data is allowed to look like.</p><p>But before we could even load a model, we had to build the roads. And that&#x2019;s where the infrastructure design fallacies kicked down the door.</p><h2 id="pitfall-1-the-simple-network-fallacy-cti-net">Pitfall 1: The &quot;Simple&quot; Network Fallacy (<code>cti-net</code>)</h2><p>The expectation was classic homelab laziness: spin up a few separate Docker Compose stacks for each application, let them map their default bridges, and expect them to magically resolve each other by hostname.</p><p>The messy reality? Independent Compose stacks love creating isolated, siloed networks by default. TheHive couldn&#x2019;t resolve MISP, the web crawlers were blind, data handoffs were dropping webhooks like crazy, and the whole stack was yelling network timeout errors back into the logs.</p><p>We debated the classic architecture fork: a monolithic <code>docker-compose.yml</code> that wraps everything under one giant config versus totally isolated stacks. Monoliths are an absolute nightmare to maintain or update independently; pure isolation breaks the integration entirely.</p><p>The fix required a fundamental mental shift&#x2014;infrastructure has to come first. We had to manually define a shared external system network called <code>cti-net</code> across the host hypervisor space before deploying a single tool. You build the roads before you construct the houses.</p><h3 id="the-blueprint">The Blueprint</h3>
<!--kg-card-begin: html-->
<div class="mermaid">
graph TD
    subgraph Host Network Space
    External[cti-net: Shared External Network]
    end
    MISP[MISP Container] --&gt; External
    TheHive[TheHive Container] --&gt; External
    OpenCTI[OpenCTI Container] --&gt; External
    n8n[n8n Automation Ingress] --&gt; External
</div>
<!--kg-card-end: html-->
<pre><code class="language-yaml"># Manual network provision on the host command line:
# docker network create cti-net

networks:
  cti-net:
    external: true</code></pre><p>Voila! Every service now registers onto the same sovereign highway, resolving each other seamlessly by their internal container handles. Network fallacy solved. Volume permissions? That was a far uglier beast.</p><h2 id="pitfall-2-the-volume-permission-nightmare">Pitfall 2: The Volume Permission Nightmare</h2><p>Docker makes downloading enterprise software incredibly lazy, right up until you try to persist the data onto physical host disks and Linux file permissions turn into absolute hell.</p><p>When you scale a CTI stack, you&apos;re dealing with disparate upstream container standards. PostgreSQL runs natively as UID 70. ElasticSearch wants to run as UID 1000. Redis drops onto another custom UID entirely. The second you map these container directories to persistent host folders on your local NVMe storage array, the ownership structures mismatch, the deployment drops into a <code>CrashLoopBackOff</code>, and the console logs start screaming <code>Permission denied</code>.</p><p>I&apos;ve seen folk try to bypass this by blindly running <code>chmod 777</code> across their entire storage pool. Don&apos;t do that. It&#x2019;s a lazy, shameful quick-fix that completely breaks file system security and leaves your underlying infrastructure naked.</p><p>We needed automation, not manual dirty hacks. The turning point was crafting a dedicated baseline janitor script&#x2014;<code>fix-permissions.sh</code>&#x2014;that executes at the host level right before the stack is brought up. It parses our targeted database and directory layouts, forcefully aligning the host folder ownership parameters to match exactly what the internal container engines require.</p><h3 id="the-workaround-fix-permissionssh">The Workaround: <code>fix-permissions.sh</code></h3><pre><code class="language-bash">#!/bin/bash
# fix-permissions.sh: Host-level janitor script for the CTI storage layout
echo &quot;Automating volume ownership parameters for cti-net stack...&quot;

# Hard-set exact paths relative to your local storage mount
CTI_DATA_DIR=&quot;/opt/stacks/cti-data&quot;

# PostgreSQL volume alignment (UID 70)
sudo chown -R 70:70 ${CTI_DATA_DIR}/postgres

# ElasticSearch volume alignment (UID 1000)
sudo chown -R 1000:1000 ${CTI_DATA_DIR}/elasticsearch

# Redis volume alignment
sudo chown -R 999:999 ${CTI_DATA_DIR}/redis

echo &quot;Volume ownership verified. Keys to the castle distributed safely.&quot;</code></pre><p>Now, we wrap this step directly into our host deployment workflow. No manual directory tracking, no security compromises, and no more silent volume launch failures.</p><p>With the roads laid and the volume maps behaving themselves, Act I is officially on the grid. Next up in Post 2, we&#x2019;re tackling what happens when MISP and Traefik get into an existential fight over port mapping, Nginx falls into an infinite redirection loop, and ElasticSearch tries to eat every byte of system memory on the server array.</p><p>Until then, see ya later. Happy tinkering!</p>]]></content:encoded></item><item><title><![CDATA[Revamping My Homelab Network with AI Assistance: A Year with the UniFi Cloud Gateway Max (Part 1 – The Brainstorming Spark)]]></title><description><![CDATA[<p>Hey everyone, it&apos;s January 10, 2026, and looking back, it&apos;s been almost exactly a year since I unboxed that UniFi Cloud Gateway Max on January 17, 2025. What started as a quick upgrade has turned into a quiet game-changer for my setup&#x2014;mostly because life</p>]]></description><link>https://blog.threatresearcher.com/revamping-my-homelab-network-with-ai-assistance-a-year-with-the-unifi-cloud-gateway-max-part-1-the-brainstorming-spark/</link><guid isPermaLink="false">6962c8a85c00b9028f2327f1</guid><category><![CDATA[ZFS]]></category><category><![CDATA[Proxmox VE]]></category><category><![CDATA[UniFi]]></category><category><![CDATA[Dell]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sat, 10 Jan 2026 22:33:26 GMT</pubDate><media:content url="https://blog.threatresearcher.com/content/images/2026/01/image.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.threatresearcher.com/content/images/2026/01/image.jpg" alt="Revamping My Homelab Network with AI Assistance: A Year with the UniFi Cloud Gateway Max (Part 1 &#x2013; The Brainstorming Spark)"><p>Hey everyone, it&apos;s January 10, 2026, and looking back, it&apos;s been almost exactly a year since I unboxed that UniFi Cloud Gateway Max on January 17, 2025. What started as a quick upgrade has turned into a quiet game-changer for my setup&#x2014;mostly because life got in the way and the homelab sat mostly idle for months. But now that things are calming down, I&apos;ve had time to reflect, optimize, and even lean on AI to guide the rearchitecture. This ties right into my ongoing experiments with local LLMs and AI workflows (Ollama evals, GPT-4o vs. locals, etc.)&#x2014;using chat models not just for quick answers, but to frame real decisions when time is short.<br><br>The unboxing was low-key: excited phablet-typing at low battery, but the real story is the upgrade path. I kept the old Cloud Key Gen2 Plus (UCK-G2-PLUS) since UniFi Protect was already set up perfectly&#x2014;cameras, NVR, all humming. Instead of a full migration (which bombed on my first restore attempt&#x2014;network reconfiguration fail, thumbtack reset drama), I just adopted it into the new Gateway Max as a pseudo-dedicated NVR. Smooth controller integration, offloads video processing, and keeps the main gateway focused on routing/firewall/visibility. Pro tip: Document everything&#x2014;VLANs, firewall rules, port maps. I learned that the hard way.<br><br>No AI for choosing between Cloud Gateway Max and Ultra&#x2014;that was standard research, heavily influenced by <a href="https://evanmccann.net/blog/ubiquiti/unifi-comparison-charts?referrer=grok.com&amp;ref=blog.threatresearcher.com#fnr1" rel="noreferrer">Evan McCann&apos;s excellent comparison charts</a>.  The Max&apos;s compact form, 2.5Gbps ports, and solid IDS/IPS headroom for home/SOHO fiber made it the clear pick for low upkeep.<br><br>But when it came to the deeper homelab rearchitecture&#x2014;storage pools, ZFS tweaks, degrowth from power-hungry enterprise gear&#x2014;I threw the initial prompt at several big chatbots: Perplexity, Grok, Copilot, and Gemini. Gemini Pro (specifically Gemini 3 in that session) stood out with the most comprehensive, context-aware response that built directly on my details without needing much re-prompting. It suggested ditching RAIDZ1 for striped mirrors, provided copy-paste commands, and spotted pitfalls I missed. We can dive deeper into why Gemini won (and how context size played a role) in a follow-up post&#x2014;I&apos;ll link it here once it&apos;s live. For now, the key takeaway: AI framed the whole pivot perfectly, saving me hours during a quick <em>sous vide</em> wait (because why not?). Project done, celebrated with a nice steak and a glass of Argentinian Malbec&#x2014;pure instant gratification.</p><p>Looking back at this past year, the real starting point of my homelab rearchitecture wasn&apos;t the hardware changes or the final ZFS commands&#x2014;it was a single, focused chat session with Gemini Pro (Gemini 3) in November 2025, about half a year past the time I wrapped-up the <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-3/" rel="noreferrer">Proxmox VE three-part series</a> (May 2025). I needed to solve a classic homelab dilemma: my existing ZFS pools (<em>basin</em>, <em>pond</em>, <em>stank</em>) were mismatched RAIDZ1 setups that throttled random-write IOPS for heavy log ingestion in Wazuh and OpenCTI, while the MD1200 DAS was a noisy, power-hungry relic I no longer needed for capacity. The goal was a cleaner, faster <em>flashpool</em> using striped mirrors, zero-downtime migration of all LXCs/VMs, and future-proofing without buying new drives.</p><p>Instead of spinning up <a href="https://blog.threatresearcher.com/n8n-in-turnkey-linux-node-js-and-in-docker/" rel="noreferrer"><em>n8n</em></a> (general workflow automation with 300+ nodes, great for complex pipelines) or <a href="https://blog.threatresearcher.com/measuring-azure-openai-gpt4o-vs-ollama-models/" rel="noreferrer"><em>Flowise</em></a> (LangChain-based low-code builder for RAG chatbots, vector search, chunking, and multi-agent flows), I just pasted my full hardware context into Gemini and let the conversation flow naturally. Modern <a href="https://blog.threatresearcher.com/extending-llama-3-8b-with-1-million-context-by-gradient/" rel="noreferrer">LLMs&apos; context windows</a> (Gemini 3 Pro supports up to 1 million input tokens, though practical chat sessions often operate effectively in the 32K&#x2013;128K range for speed) meant it remembered every detail across turns&#x2014;no re-explaining hardware, no chunking strategies, no vector DB setup. I could discuss concerns (&quot;Striped mirrors will sacrifice some capacity&#x2014;worth it?&quot;), refine aspirations (&quot;Prioritize reliability for self-hosted sec tools over bulk storage&quot;), and get grounded suggestions with built-in reasoning.</p><p>It felt like having a knowledgeable homelab partner at 2 a.m.&#x2014;when no one else in the house cares about RAID trade-offs or <em>ashift</em> values. I argued points, it pushed back with logic, and it architected the end state first (<em>flashpool</em> as the target), then handed tactical steps&#x2014;including the key storage migration I used to move every LXC (from Pi-hole to Immich) to <em>rpool</em> via Proxmox&apos;s &quot;Move Disk&quot; feature (GUI or <em>qm migrate</em> CLI).</p><p>The biggest value here isn&apos;t just code generation (though the copy-paste commands were spot-on)&#x2014;it&apos;s the shift from &quot;<em>build your own RAG pipeline</em>&quot; to instant, conversational architecture. In the past, for a similar deep dive I&apos;d spin up n8n or Flowise, requiring nodes, connectors, chunking strategies, vector DB setup, and testing loops&#x2014;hours of plumbing before you even get useful output. With modern LLMs&apos; massive context windows and native capabilities, I skipped all that. No pipeline setup, no chunking debates&#x2014;just describe the problem, argue concerns, refine aspirations, and get grounded suggestions with search grounding if needed. It feels like a 2 a.m. homelab buddy who remembers your entire setup across turns, no one else in the house needs to care.</p><p>This usability leap has opened doors for more efficient &quot;code vibing&quot; homelab projects&#x2014;iterating fast on configs, scripts, or even full services without heavy orchestration. (That&apos;s fodder for another post: what&apos;s up with Antigravity, Cursor, and Claude Code in the agentic coding space? Early 2026 vibes are wild&#x2014;Google&apos;s Antigravity as an agent-first IDE with autonomous planning/execution via Gemini 3, Cursor as the refined VS Code AI accelerator, Claude Code for terminal-deep reasoning and autonomous refactors. More on that soon.)</p><p>Here&apos;s the key part of that brainstorming flow (<em>lightly edited for readability, but preserving the back-and-forth feel&#x2014;full history attached for reference</em>). I&apos;ve pulled directly from the conversation to ground everything in truth: Gemini&apos;s suggestions were tailored to my described future requirements (high-IOPS for sec tools, single-node simplicity, power/noise reduction), and it emphasized migration to <em>rpool</em> first as a safety net.</p><p><strong>My initial prompt (dumping hardware + goals, as in chat):</strong></p><blockquote>i&apos;m rebuilding my tech stack and plan to host most everything in Proxmox VE via LXD as much as possible. this is currently in my plan: Shuffle aka Shuffler, Wazuh, OpenCTI, MISP, AIL Project</blockquote><p><strong>Gemini&apos;s response (key excerpts&#x2014;framed the strategy, split into native vs. Docker-in-LXC based on my requirements):</strong></p><blockquote>This is a highly feasible plan. You can host nearly 100% of this stack in LXC containers on Proxmox... Prioritizes the Proxmox VE Helper-Scripts... Type A: Native LXC (Best Performance) Tools: Wazuh, MISP, AIL... Type B: Docker-in-LXC (Easiest Maintenance) Tools: Shuffle, OpenCTI...</blockquote><blockquote>Wazuh (SIEM) Recommendation: Use the Community Helper Script... Command: Run the community script command in your Proxmox shell to spawn a dedicated &quot;Wazuh&quot; LXC... Allocate at least 8GB RAM...</blockquote><blockquote>Shuffle (SOAR) Recommendation: Docker-in-LXC... Use the Docker LXC helper script... Caveat: Shuffle uses Opensearch. You must set vm.max_map_count=262144 on the Proxmox Host...</blockquote><p>And so on for each tool, with detailed methods.</p><p><strong>Follow-up prompts/responses (iterating on Dockge, Podman, CasaOS&#x2014;Gemini argued against Podman for my stack, suggested Dockge):</strong></p><blockquote>User: I also previously used Portainer CE but can forego that if there is a simpler solution... I&apos;ve also started to experiment on Podman...</blockquote><blockquote>Gemini: This is a common pivot... Switch to Dockge... Why avoid Podman for Shuffle/OpenCTI? Networking Complexity... Socket Binding... Documentation... Revised Plan: ... bash -c &quot;$(wget -qO - <a href="https://github.com/community-scripts/ProxmoxVE/raw/main/ct/docker.sh?referrer=grok.com&amp;ref=blog.threatresearcher.com" rel="noopener noreferrer nofollow">https://github.com/community-scripts/ProxmoxVE/raw/main/ct/docker.sh</a>)&quot; ... curl <a href="https://raw.githubusercontent.com/louislam/dockge/master/install.sh?referrer=grok.com&amp;ref=blog.threatresearcher.com" rel="noopener noreferrer nofollow">https://raw.githubusercontent.com/louislam/dockge/master/install.sh</a> | sh</blockquote><p><strong>On TrueNAS/CasaOS/MD1200 pivot (Gemini suggested PCI passthrough for TrueNAS VM, warned on MD1200 issues like fan noise):</strong></p><blockquote>User: I&apos;m also interested in Casa OS... re-install TrueNAS Scale as a container but physically tie it to control my Dell MD1200 array...</blockquote><blockquote>Gemini: This part of your plan needs a course correction... CasaOS: Skip it, redundant with Dockge... TrueNAS Scale: Must run as VM, not container... PCI Passthrough for HBA card... Warnings for MD1200 + SSDs: Fan Noise (The &quot;Jet Engine&quot; Problem)... 6Gbps Limit... Interposers...</blockquote><p><strong>Core storage rearchitecture (the big one&#x2014;Gemini suggested migration first, then destroy/wipe/create based on my goals):</strong></p><blockquote>User: ...the script did not seem to detect the previous installation</blockquote><blockquote>Gemini: ...Before doing anything, stop the container and take a manual snapshot... Verify your Current Version: /var/ossec/bin/wazuh-control info... Manual Update Sequence: apt-get update... apt-get install --only-upgrade wazuh-indexer -y... etc.</blockquote><p>Later turns focused on pool states:</p><blockquote>Gemini: pool: basin... config: raidz1-0... (full before states as extracted)</blockquote><blockquote>After user shared zpool status: Suggest striped mirrors for flashpool, with exact create command matching my devices.</blockquote><blockquote>Migration: &quot;Use Proxmox&apos;s Move Disk in the GUI to relocate containers/VMs to rpool first&#x2014;zero downtime&#x2014;before destroying old pools.&quot;</blockquote><p>Full commands from Gemini (as I executed&#x2014;always test/back up first!):</p><blockquote>Bash</blockquote><pre><code># Migration (per container/VM)
qm config &lt;ID&gt;  # Check current disk
qm migrate &lt;ID&gt; --targetstorage rpool  # Or GUI: Hardware &gt; Disk &gt; Move Disk</code></pre><blockquote>Bash</blockquote><pre><code># Destroy (post-migration)
zpool destroy basin
zpool destroy pond
zpool destroy stank</code></pre><blockquote>Bash</blockquote><pre><code># Wipe
for disk in sdc sdd sde sdf sdg sdh sdi sdj sdk sdl sdm; do
  wipefs -af /dev/$disk
  sgdisk --zap-all /dev/$disk
done
partprobe /dev/sd[c-m]</code></pre><blockquote>Bash</blockquote><pre><code># Create flashpool
zpool create -f -o ashift=12 flashpool \
  mirror scsi-36b083fe0dffbfa002d21cca4172514ec scsi-36b083fe0dffbfa002d21ccbb187797e4 \
  mirror scsi-36b083fe0dffbfa002d21cf9227b92ed4 scsi-36b083fe0dffbfa002de694ac1f246e22 \
  mirror scsi-36b083fe0dffbfa002de694ab1f06447c scsi-36b083fe0dffbfa002de694ab1f10ce50 \
  mirror scsi-36b083fe0dffbfa002de694ac1f16b6a1 scsi-36b083fe0dffbfa002de694ac1f1e4a2c \
  mirror scsi-36b083fe0dffbfa002de694ad1f2bbbbf scsi-36b083fe0dffbfa002de694ad1f3282b5</code></pre><blockquote>Bash</blockquote><pre><code># Tuning
zfs set compression=lz4 flashpool
zfs set atime=off flashpool
zfs set xattr=sa flashpool
zfs set recordsize=64k flashpool
# Quotas for sec datasets
zfs create flashpool/sec-stack
zfs set quota=4T flashpool/sec-stack</code></pre><blockquote>Bash</blockquote><pre><code># Register
pvesm add zfs flashpool --pool flashpool --content images,rootdir --sparse 1</code></pre><p>Before/after pool states (direct from chat&#x2014;Gemini echoed my zpool status, then suggested the new config):</p><ul><li><strong>Before (<em>basin</em> example)</strong>: raidz1-0 with three drives, ONLINE.</li><li><strong>After (<em>flashpool</em>)</strong>: Five mirrors, ONLINE&#x2014;matched my SSD count for striped performance.</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2026/01/Screenshot-2026-01-10-at-4.18.48-PM.png" class="kg-image" alt="Revamping My Homelab Network with AI Assistance: A Year with the UniFi Cloud Gateway Max (Part 1 &#x2013; The Brainstorming Spark)" loading="lazy" width="1326" height="260" srcset="https://blog.threatresearcher.com/content/images/size/w600/2026/01/Screenshot-2026-01-10-at-4.18.48-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2026/01/Screenshot-2026-01-10-at-4.18.48-PM.png 1000w, https://blog.threatresearcher.com/content/images/2026/01/Screenshot-2026-01-10-at-4.18.48-PM.png 1326w" sizes="(min-width: 720px) 720px"></figure><p>This collaborative vibe&#x2014;argue, refine, confirm&#x2014;turned a potential headache into a sous-vide-session project (steak + Malbec celebration still the highlight). No RAG pipeline, no chunking debates, just instant, context-aware architecture.</p><p>The payoff? A clean <em>flashpool</em> rebuild, MD1200 shutdown (kept as optional expansion), and a lighter, more reliable homelab&#x2014;all sparked by one chat that felt collaborative, not mechanical. Sous-vide steak + Malbec celebration? Still unbeatable.</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2026/01/Screenshot-2026-01-10-at-4.16.04-PM.png" class="kg-image" alt="Revamping My Homelab Network with AI Assistance: A Year with the UniFi Cloud Gateway Max (Part 1 &#x2013; The Brainstorming Spark)" loading="lazy" width="2000" height="1301" srcset="https://blog.threatresearcher.com/content/images/size/w600/2026/01/Screenshot-2026-01-10-at-4.16.04-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2026/01/Screenshot-2026-01-10-at-4.16.04-PM.png 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2026/01/Screenshot-2026-01-10-at-4.16.04-PM.png 1600w, https://blog.threatresearcher.com/content/images/2026/01/Screenshot-2026-01-10-at-4.16.04-PM.png 2000w" sizes="(min-width: 720px) 720px"></figure><p>In a follow-up, we&apos;ll compare why Gemini Pro edged out Perplexity/Grok/Copilot here (context retention, native tools), and tease more on emerging coding agents. </p><p>Drop your own 2 a.m. AI partner moment below&#x2014;what&apos;s the wildest late-night homelab win you&apos;ve had with chat alone? &#x1F604;</p>]]></content:encoded></item><item><title><![CDATA[Waiting for the Home Assistant CLI to be ready...]]></title><description><![CDATA[<p>Let me start by saying that I&apos;ve figured out a repeatable way to get around this issue which had stumped me all week! And, here&apos;s the proof:</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery.jpg" width="2000" height="781" loading="lazy" alt srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_154944_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_154944_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_154944_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155000_Gallery.jpg" width="2000" height="781" loading="lazy" alt srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_155000_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_155000_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_155000_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155000_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155006_Gallery.jpg" width="2000" height="781" loading="lazy" alt srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_155006_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_155006_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_155006_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155006_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>Let&apos;s back up a second and talk about what happened and what got us here. Previously, these</p>]]></description><link>https://blog.threatresearcher.com/waiting-for-the-home-assistant-cli/</link><guid isPermaLink="false">68bde0bf6cf0b20284c71c46</guid><category><![CDATA[home assistant]]></category><category><![CDATA[hassos]]></category><category><![CDATA[IoT]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Sun, 07 Sep 2025 21:17:28 GMT</pubDate><media:content url="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-7.59.41-PM.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-7.59.41-PM.png" alt="Waiting for the Home Assistant CLI to be ready..."><p>Let me start by saying that I&apos;ve figured out a repeatable way to get around this issue which had stumped me all week! And, here&apos;s the proof:</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery.jpg" width="2000" height="781" loading="lazy" alt="Waiting for the Home Assistant CLI to be ready..." srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_154944_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_154944_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_154944_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155000_Gallery.jpg" width="2000" height="781" loading="lazy" alt="Waiting for the Home Assistant CLI to be ready..." srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_155000_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_155000_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_155000_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155000_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155006_Gallery.jpg" width="2000" height="781" loading="lazy" alt="Waiting for the Home Assistant CLI to be ready..." srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_155006_Gallery.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_155006_Gallery.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_155006_Gallery.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_155006_Gallery.jpg 2316w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>Let&apos;s back up a second and talk about what happened and what got us here. Previously, these things happened (not in any specific order):</p><ul><li>An urgent message was received one day from someone at home that the &quot;internet was dead&quot;. That situation was true for about a fully day overnight since it required an ISP technician to come inspect their fiber hardware. I was able to get some very minimal IoT smart devices working but nothing that needed the &quot;cloud&quot; worked.</li><li>At an average of about 11-cents/kWh the servers typically hit at $30~50/month prior to summer on-set and more than likely, due to their garage location in North Texas hea, would register more if I did a new Kill-a-Watt measurement. As it is, they&apos;re running at a noisy full-tilt instead of the normal 20% speed.</li><li> A mix of both ARM64 and AMD64 machines in a  Proxmox VE cluster is not the most optimal way to run things due to inconsistencies of storage media and other dependencies.</li><li>Recently de-clustering my high-availability setup due to the resulting heat and aforementioned cost of running a #homelab and job function change.</li><li>Wanting to find a way to setup Frigate and leverage the Coral Dual Edge TPU and PCIe 1x adapter but finding all current market options too costly or power hungry</li></ul><p>These are our current cast of characters: old laptop hand-me-downs from my now no-longer teenage son in the forms of an Acer Aspire V5-122P (AMD) and an Acer Aspire E5-576 (Intel with QuickSync). These had previously been pre-installed with Windows 7 and I had then flashed with the latest Ubuntu Desktop at the time of being received.</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/PXL_20250902_202114316.jpg" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="2000" height="1125" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/PXL_20250902_202114316.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/PXL_20250902_202114316.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/PXL_20250902_202114316.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/PXL_20250902_202114316.jpg 2000w" sizes="(min-width: 720px) 720px"></figure><p>I then followed the appropriate hardware install instructions for the official <a href="https://www.home-assistant.io/installation/generic-x86-64?ref=blog.threatresearcher.com" rel="noreferrer">Home Assistant Operating System Generic x86-64</a> which called for enabling UEFI Boot and disabling Secure Boot (because HassOS uses Buildroot and a customized version of Linux). </p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.27.32-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1378" height="1616" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-5.27.32-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-5.27.32-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.27.32-PM.png 1378w" sizes="(min-width: 720px) 720px"></figure><blockquote>Let me digress here and mention that about two-(2) weeks prior I had been looking into converting at least one of the Nano Pi R5S into Home Assistant hosts but wasn&apos;t getting very far since I had to figure out how to merge separate Buildroot processes, one for HA and the other to incorporate the Rockchip drivers.</blockquote><p>There are some older instructions out there that talks about setting EFI and all that but in my experience those options only came into play when Secure Boot <em>was</em> enabled initially in-order for you to basically reset the options to factory defaults. But if you find yourself in a bind, then feel free to try it out just to remove variables:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.31.46-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1382" height="842" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-5.31.46-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-5.31.46-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.31.46-PM.png 1382w" sizes="(min-width: 720px) 720px"></figure><p>I initially decided to go full steam ahead and use the Aspire E5-576 as the main HA unit and,  also, wanted it to be running Frigate, Jellyfin, Plex, and a whole host of different things to make full use of the overpowered hardware and Intel Quick Sync. However, the way HassOS is envisioned right now is that it needs to boot pristine without any other things loaded with it during the back-end Docker boot-up. Anything more than that then the installation will complain and you will get the <em>Unsupported</em> nod from Home Assistant observer and that would not be a happy experience, trust me:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.36.26-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1684" height="554" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-5.36.26-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-5.36.26-PM.png 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot-2025-09-07-at-5.36.26-PM.png 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-5.36.26-PM.png 1684w" sizes="(min-width: 720px) 720px"></figure><p>So, I pivoted and decided to use the Acer Aspire V5-122P, which only had 500GB of storage, to instead be a sort of head-end and call the Quick Sync enabled machine remotely as a service. Those of us dabbling with AI automation will recognize this as using <em>Agents</em> that do their own autonomous activities. </p><p>But, that wasn&apos;t before I had already been hitting my head on the wall no matter what I did as a work-around to get past booting into this frustrating message: </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery-1.jpg" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="2000" height="781" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot_20250907_154944_Gallery-1.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot_20250907_154944_Gallery-1.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot_20250907_154944_Gallery-1.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot_20250907_154944_Gallery-1.jpg 2000w" sizes="(min-width: 720px) 720px"><figcaption><i><em class="italic" style="white-space: pre-wrap;">Waiting for the Home Assistant CLI to be ready...</em></i></figcaption></figure><p>I&apos;ve been all around the support groups and discussions and even found <a href="https://github.com/home-assistant/operating-system/issues/2272?ref=blog.threatresearcher.com" rel="noreferrer">a bug report</a>, which did give me a clue!</p><p>Within those workarounds someone talked about renaming labels and partitions and that may be true in some situations where the installation has progressed to completion. I&apos;m only repeating the post here because it taught me a little about getting a separate terminal out of HA without breaking it further: <strong>Ctrl-Alt-F2</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.18.04-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1826" height="1318" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.18.04-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-6.18.04-PM.png 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot-2025-09-07-at-6.18.04-PM.png 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.18.04-PM.png 1826w" sizes="(min-width: 720px) 720px"></figure><p>However, the whole thing about workarounds and renaming labels falls apart because there is <strong><em>nothing to fix</em></strong>, and by that I mean that is what if the partitions and all that underlying stuff may have failed in various ways and there&apos;s nothing to operate those fixes on. The key for me was noticing the <strong><em>Dependency failed</em></strong> part of the boot process:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.05.13-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="848" height="402" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.05.13-PM.png 600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.05.13-PM.png 848w" sizes="(min-width: 720px) 720px"></figure><p>This, my friends, was my <em>aha! moment</em>, the part where latent pieces of the boot and file structure might not have been correctly expunged from the system. </p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.13.58-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1918" height="806" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.13.58-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-6.13.58-PM.png 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot-2025-09-07-at-6.13.58-PM.png 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.13.58-PM.png 1918w" sizes="(min-width: 720px) 720px"></figure><p>Whether it is a bug or not is debatable. What is important is that removing this part of the information is the key. So, back to the recommended <em>Method 1</em> of the official HA installation, before I restored the HassOS image I decided to wipe the disk with zero&apos;s as well as remove all partitions. </p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.36.57-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1254" height="628" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.36.57-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-6.36.57-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.36.57-PM.png 1254w" sizes="(min-width: 720px) 720px"></figure><p>However, as you can see that was going to be more than a seven-(7) hour process for a 1TB disk:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/PXL_20250906_165733270.jpg" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="2000" height="1125" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/PXL_20250906_165733270.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/PXL_20250906_165733270.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/PXL_20250906_165733270.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/09/PXL_20250906_165733270.jpg 2000w" sizes="(min-width: 720px) 720px"></figure><blockquote>I would not fault you, dear readers, if you haven&apos;t had any digital forensic background to understand the <a href="https://en.wikipedia.org/wiki/GUID_Partition_Table?ref=blog.threatresearcher.com" rel="noreferrer">GUID Partition Table (GPT)</a> But, it should suffice to say that overwriting that minimum 1% (one percent) of the disk would be more than enough to clear out the data and disassociate most of the disk information from mapping. Back in the days of boot sector viruses this place of the disk was always under contention because it presented a way for malware to load prior to the operating system and circumvent security protections and many other shenanigans!</blockquote><p>To proof my theory, I decided to do the same data clearing for the 500GB disk on the Acer V5:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.45.47-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1300" height="790" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.45.47-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-6.45.47-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.45.47-PM.png 1300w" sizes="(min-width: 720px) 720px"></figure><p>Once completing the image restore you should get a layout similar to this:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.47.04-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1354" height="718" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-6.47.04-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-6.47.04-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-6.47.04-PM.png 1354w" sizes="(min-width: 720px) 720px"></figure><p>The only things to do now are to shutdown Live Ubuntu session, disconnect all external drives, connect any special hardware, boot-up, and (optionally) <a href="https://www.home-assistant.io/common-tasks/general/?ref=blog.threatresearcher.com#restoring-a-backup" rel="noreferrer">restoring from backup</a>.</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-8.06.26-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1968" height="682" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-8.06.26-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-8.06.26-PM.png 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/09/Screenshot-2025-09-07-at-8.06.26-PM.png 1600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-8.06.26-PM.png 1968w" sizes="(min-width: 720px) 720px"></figure><p>I&apos;m going to give it about a week of live testing for functionality as well as looking at the power consumption from the wall. If things are stable then I might just shutdown the virtualized version and stick with this laptop version. </p><p>The next step of the puzzle is how to make use of the space beyond what the default HassOS image allocates by default for itself, approximately 30GB. I&apos;m going to try to tackle that in a follow-up:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-7.40.53-PM.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="1226" height="536" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-2025-09-07-at-7.40.53-PM.png 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/09/Screenshot-2025-09-07-at-7.40.53-PM.png 1000w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-2025-09-07-at-7.40.53-PM.png 1226w" sizes="(min-width: 720px) 720px"></figure><p>There is a mismatch somewhere in terms of what HassOS reports compared to how things are actually mapped on-disk. Here&apos;s what GParted reports from a Live Ubuntu session:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/09/Screenshot-from-2025-09-08-03-54-33.png" class="kg-image" alt="Waiting for the Home Assistant CLI to be ready..." loading="lazy" width="803" height="566" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/09/Screenshot-from-2025-09-08-03-54-33.png 600w, https://blog.threatresearcher.com/content/images/2025/09/Screenshot-from-2025-09-08-03-54-33.png 803w" sizes="(min-width: 720px) 720px"></figure><p>As can be seen, and similarly claimed during the installation process, the hassos-data partition did, in fact, expand to the rest of the disk. Why then is the built-in Disk metrics only reporting about 10GB left of free space? If you happen to come by this post and have an explanation, feel free to add it in the comments.</p><p>As for the Aspire E5, I&apos;m currently leaning towards making it into just a full blown Docker or Podman host. The reason being that if I installed Proxmox VE on top of it then I&apos;d have to contend with the extra hypervisor overhead on an already system memory challenged system. A simple Ubuntu or Debian Bookworm bare metal server installation might net me just the right amount of processing utility that I need.</p><p>See you next time.</p>]]></content:encoded></item><item><title><![CDATA[I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 3]]></title><description><![CDATA[<p>Welcome back, it&apos;s literally been a minute since I published <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-2/" rel="noreferrer"><em>Part 2</em> of this series where I found a fix for the Pi-hole NTP sync errors</a>.</p><p>I don&apos;t think there&apos;s going to be a separate need to discuss blogging on <a href="https://blog.threatresearcher.com/the-3rd-return-from-being-offline/" rel="noreferrer">Ghost via mobile</a>. It</p>]]></description><link>https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-3/</link><guid isPermaLink="false">682bacd35a4048028cb5b43f</guid><category><![CDATA[Proxmox VE]]></category><category><![CDATA[Homelab]]></category><category><![CDATA[LXC]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Mon, 19 May 2025 22:15:40 GMT</pubDate><media:content url="https://blog.threatresearcher.com/content/images/2025/05/1000018738.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.threatresearcher.com/content/images/2025/05/1000018738.jpg" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 3"><p>Welcome back, it&apos;s literally been a minute since I published <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-2/" rel="noreferrer"><em>Part 2</em> of this series where I found a fix for the Pi-hole NTP sync errors</a>.</p><p>I don&apos;t think there&apos;s going to be a separate need to discuss blogging on <a href="https://blog.threatresearcher.com/the-3rd-return-from-being-offline/" rel="noreferrer">Ghost via mobile</a>. It should suffice to say that copy-pasting images works better on Chrome mobile mode; you can get better native desktop-mode experience when using Firefox. The capability to flip back-and-forth seamlessly is a game changer for speed edits. I&apos;m not sure about the experience using an actual tablet like the Google Pixel Tablet or a Chromebook like the <a href="https://www.costco.com/acer-chromebook-plus-14%22-touchscreen-laptop-with-google-ai---intel-core-i3-n305---1920-x-1080---chrome-os---8gb-ram---512gb-ssd---protective-sleeve-included.product.4000252543.html?ref=blog.threatresearcher.com" rel="noreferrer">Acer Chromebook Plus 14&quot;</a> (CB514-4HT-359X) but that&apos;s going to be one of the next experiments. My final edits have been on the old MacBook Pro, whenever it&apos;s still got a charge.</p><h3 id="part-3-proxmox-ve-helper-scripts-meets-xda-developers">Part 3: Proxmox VE Helper scripts meets XDA Developers </h3><p>Let me start with the elephant in the room, why use LXC instead of using the existing Docker VMs in my current stack? Well, let&apos;s talk about that. </p><p>I&apos;ve been running MISP and OpenCTI for the longest time in a cluster for high-availability. Specifically, ElasticSearch can become unwieldy when you try to give it the best possible scenario when you&apos;ve got limited rack space expansion and a power budget cap. Essentially, because of this I&apos;m considering a re-do and clawing back resources these projects have taken over in resources. Plus, I&apos;ve recently had some bad spells with old Portainer versions that over time has given me a bad taste in the mouth. And then, from the last time I had touched edits on Docker did Podman enter the picture. So far, in the past few months this might be the direction I take if only so I can learn more about it&apos;s pitfalls and the fact it is what you would get to use in a locked-down Red Hat enterprise image. There&apos;s alot to unpack there, but my point is that I don&apos;t take this decision lightly. There&apos;s going to be a learning curve and trade-offs to be made. I&apos;ll have to be OK with that. So, this is why we&apos;re going back to individual containers in the form of LXC instead of full VMs if we don&apos;t have to.</p><p>Now, with that out of the way, a brief note on <a href="https://en.wikipedia.org/wiki/Valnet?ref=blog.threatresearcher.com#XDA" rel="noreferrer">XDA Developers</a>. Hailing from the Philippines, I&apos;ve been on the cutting edge of mobile computing since back in the Nokia days. If I couldn&apos;t get new stuff locally then I could always hop on a plane to Singapore and visit <a href="https://www.simlimsquare.com.sg/?ref=blog.threatresearcher.com" rel="noreferrer"><em>Sim Lim Square</em></a>. And, on one of these trips is where I got hold of my first <a href="https://en.wikipedia.org/wiki/O2_Xda?ref=blog.threatresearcher.com" rel="noreferrer"><strong>O2 XDA</strong></a> (and a bunch of Havaianas). Mind you, at around this time I was sporting the latest <a href="https://en.wikipedia.org/wiki/Nokia_9500_Communicator?ref=blog.threatresearcher.com" rel="noreferrer">Nokia 9500 Communicator.</a> I was ready for another form factor, let those parts sink in. Rooting and hacking bleeding edge mobile devices is how XDA and I crossed paths. Years later after transformation I really enjoy the <a href="https://www.xda-developers.com/search/?q=self-host&amp;ref=blog.threatresearcher.com" rel="noreferrer">self hosted section topics</a> for my use case.</p><p>About <a href="https://community-scripts.github.io/ProxmoxVE/?ref=blog.threatresearcher.com" rel="noreferrer">Proxmox VE Helper scripts</a>, I discovered this group while looking to experiment with lightweight versions of my homelab projects. What I would do was learn from the scripts and incorporate or improve on them for my specific use case. Now, however, I plan to use several of the templates to get things restarted based on availability and if something gets mentioned over at XDA.</p><p>I&apos;ve already showed what a basic phablet install experience and experiment looks like over in <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-phablet/" rel="noreferrer">Part 1 of this series</a>. Here&apos;s where I&apos;ve landed so far:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250518_193546_Chrome.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 3" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250518_193546_Chrome.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250518_193546_Chrome.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250518_193546_Chrome.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250518_193546_Chrome.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>There&apos;s a big part of myself that cringes at the auto-numbering since my original schema was to map IP to VMID. If it matters that much later then, in theory, it should just be a matter of a backup and then restore to a specific VMID. Well, in my mind, that&apos;s how I&apos;m coping with the situation.</p><p>In Part 4, we can discuss about the use cases and groupings of what&apos;s been installed. Or, I may just launch a new series based on specific group topic projects linked stemming from here.</p><p>Happy trails.</p>]]></content:encoded></item><item><title><![CDATA[I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2]]></title><description><![CDATA[<p>Strike while the iron is hot? Well, I&apos;m going to do a version of type on this phablet until it powers down because its now at 11% and hopefully not loose any content. I guess that is part of the curse when you&apos;ve got the ideas</p>]]></description><link>https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-2/</link><guid isPermaLink="false">682a7d765a4048028cb5b3ca</guid><category><![CDATA[Proxmox VE]]></category><category><![CDATA[ARM64]]></category><category><![CDATA[Pi-hole]]></category><category><![CDATA[NanoPi]]></category><category><![CDATA[Homelab]]></category><dc:creator><![CDATA[Jamz Yaneza]]></dc:creator><pubDate>Mon, 19 May 2025 13:48:15 GMT</pubDate><media:content url="https://blog.threatresearcher.com/content/images/2025/05/1000018739.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.threatresearcher.com/content/images/2025/05/1000018739.jpg" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2"><p>Strike while the iron is hot? Well, I&apos;m going to do a version of type on this phablet until it powers down because its now at 11% and hopefully not loose any content. I guess that is part of the curse when you&apos;ve got the ideas and time is measured in either bars of battery or wifi strength.</p><p>In <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-phablet/" rel="noreferrer"><em>Part 1</em>, I talked about success in getting <em>Pihole setup on ARM64.</em></a><em> </em> There might be some other lightweight resourced projects to install or migrate later, perhaps <em>Uptime Kuma</em>?</p><h3 id="part-2-pi-hole-ntp-sync-sidequest">Part 2: Pi-hole NTP sync sidequest </h3><p>There was an <strong><em>NTP setting</em></strong> that needed to be addressed related to permissions, which by some reports is a bug or a setting that doesn&apos;t make sense depending on how you have Pihole set-up:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190225_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250517_190225_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250517_190225_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250517_190225_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190225_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>Navigate to Settings, and notice the green <strong><em>Basic</em></strong> toggle:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_185916_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250517_185916_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250517_185916_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250517_185916_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_185916_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>Click on this and you&apos;ll enter <strong><em>Expert</em></strong> mode:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_185923_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250517_185923_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250517_185923_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250517_185923_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_185923_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>A new option will then appear called <strong><em>All settings</em></strong>:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190255_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250517_190255_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250517_190255_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250517_190255_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190255_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>Within <em>All settings</em> navigate to the <strong><em>Network Time Sync</em></strong> tab and disable most of the settings:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250519_170150_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250519_170150_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250519_170150_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250519_170150_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250519_170150_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>The most important edit is zeroing the setting for ntp.syc.interval:</p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250519_170234_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250519_170234_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250519_170234_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250519_170234_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250519_170234_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p>Save your settings and you will then notice the error alert disappear: </p><figure class="kg-card kg-image-card"><img src="https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190347_Firefox.jpg" class="kg-image" alt="I restarted my homelab with Proxmox VE Helper-scripts and a phablet! - Part 2" loading="lazy" width="1812" height="2176" srcset="https://blog.threatresearcher.com/content/images/size/w600/2025/05/Screenshot_20250517_190347_Firefox.jpg 600w, https://blog.threatresearcher.com/content/images/size/w1000/2025/05/Screenshot_20250517_190347_Firefox.jpg 1000w, https://blog.threatresearcher.com/content/images/size/w1600/2025/05/Screenshot_20250517_190347_Firefox.jpg 1600w, https://blog.threatresearcher.com/content/images/2025/05/Screenshot_20250517_190347_Firefox.jpg 1812w" sizes="(min-width: 720px) 720px"></figure><p> With that out of the way, <a href="https://blog.threatresearcher.com/i-restarted-my-homelab-with-proxmox-ve-helper-scripts-and-a-phablet-part-3/" rel="noreferrer">onward to Part 3</a>.</p><p>Yes, I&apos;m still doing my edits from the Flip4!</p>]]></content:encoded></item></channel></rss>