<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Performance on Frank&#39;s Blog</title>
    <link>https://frankblogs.com/tags/performance/</link>
    <description>Recent content in Performance on Frank&#39;s Blog</description>
    <generator>Hugo -- 0.150.0</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 10 Oct 2025 21:39:48 +0800</lastBuildDate>
    <atom:link href="https://frankblogs.com/tags/performance/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Service Deployment &amp; Advanced Troubleshooting on iStoreOS</title>
      <link>https://frankblogs.com/posts/article-6/</link>
      <pubDate>Fri, 10 Oct 2025 21:39:48 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-6/</guid>
      <description>With iStoreOS running stably on my N100 Proxmox setup, it was time to deploy AdGuard Home, Tailscale, and troubleshoot lingering issues like speed bottlenecks and remote access failures. This is where the real power of the platform shone.</description>
      <content:encoded><![CDATA[<p>My N100 soft router was finally running a stable router OS – iStoreOS – within a Proxmox VE virtual machine. The core networking was solid. Now came the rewarding part: deploying the services I actually wanted and tackling the inevitable advanced troubleshooting challenges.</p>
<h2 id="adguard-home-taming-the-dns-loop">AdGuard Home: Taming the DNS Loop</h2>
<p>Installing AdGuard Home (AGH) via the iStoreOS app store was straightforward. The initial setup wizard (<code>:3000</code>) guided me through setting ports. I changed AGH&rsquo;s DNS port to <code>:5353</code> to avoid conflict with iStoreOS&rsquo;s built-in <code>dnsmasq</code> (running on <code>:53</code>).</p>
<p>The goal: <code>Clients -&gt; iStoreOS (dnsmasq :53) -&gt; AdGuard Home (:5353) -&gt; Public DNS (e.g., 1.1.1.1)</code>.</p>
<p>Configuration involved:</p>
<ol>
<li><strong>dnsmasq:</strong> Set it to <em>not</em> forward upstream queries found in <code>/etc/resolv.conf</code>, and explicitly forward <em>all</em> queries to AGH listening on the loopback address: <code>server=127.0.0.1#5353</code>.</li>
<li><strong>AdGuard Home:</strong> Set its upstream DNS servers to Cloudflare/Google.</li>
<li><strong>DHCP:</strong> Configure iStoreOS&rsquo;s DHCP server (Option 6) to advertise the router&rsquo;s IP (<code>10.0.0.1</code>) as the DNS server for all clients.</li>
</ol>
<p>Initially, this resulted in DNS resolution failures and <code>context deadline exceeded</code> errors in the AGH logs. Diagnosis: a <strong>DNS loop</strong>. Dnsmasq was forwarding to AGH, but AGH, possibly due to a misconfiguration or startup order issue, was somehow trying to query dnsmasq back.</p>
<p>Adding to the confusion was a &ldquo;ghost configuration.&rdquo; I had initially tried installing AGH via a <code>curl</code> script before using the app store version. This seemed to leave conflicting settings. The breakthrough came almost accidentally: running the AdGuard Home binary directly from the command line with the <code>-s run</code> flag (<code>./AdGuardHome -s run</code>) triggered some kind of self-reset or reinitialization. After this, restarting the service properly allowed the correct DNS chain (<code>dnsmasq -&gt; AGH -&gt; Public</code>) to establish, and DNS resolution started working beautifully across my network.</p>
<h2 id="the-network-speed-crisis-a-virtualization-bottleneck">The Network Speed Crisis: A Virtualization Bottleneck</h2>
<p>With DNS filtering active, I ran a speed test. Disaster! My gigabit fiber connection, which previously delivered ~950 Mbps, was now capped at a measly <strong>400 Mbps</strong>.</p>
<p>The troubleshooting began:</p>
<ul>
<li><strong>Disable AdGuard Home:</strong> No change. DNS filtering wasn&rsquo;t the bottleneck.</li>
<li><strong>Check Physical Links:</strong> Used <code>ethtool eth0</code> and <code>ethtool eth1</code> within the iStoreOS VM to confirm the virtual NICs were negotiating at 2500 Mbps with the PVE bridges. Links were fine.</li>
<li><strong>Enable Software Flow Offloading:</strong> Toggled this common OpenWrt optimization. No significant change.</li>
</ul>
<p>The problem had to lie deeper, likely within the virtualization layer itself. Research pointed towards a common issue with high-speed networking in VMs: the CPU struggling to handle the sheer volume of network packets being processed by a single core for the virtual NIC.</p>
<h3 id="the-solution-multiqueue">The Solution: Multiqueue</h3>
<p>Proxmox VE (and the underlying KVM/QEMU) supports a feature called <strong>Multiqueue VirtIO-Net</strong>. This allows the network packet processing load for a virtual NIC to be spread across multiple vCPU cores assigned to the VM.</p>
<ol>
<li>Shut down the iStoreOS VM.</li>
<li>In the PVE web UI, go to the VM&rsquo;s &ldquo;Hardware&rdquo; tab.</li>
<li>Select the VirtIO network device corresponding to the <strong>LAN</strong> interface (<code>net0</code> in my case, connected to <code>vmbr1</code>).</li>
<li>Click &ldquo;Edit&rdquo;.</li>
<li>Check the <strong>&ldquo;Multiqueue&rdquo;</strong> box.</li>
<li>Set the &ldquo;Queues&rdquo; number equal to the number of vCPU cores assigned to the VM (e.g., if you gave it 4 cores, set Queues to 4).</li>
<li>Repeat steps 3-6 for the <strong>WAN</strong> network device (<code>net1</code>, connected to <code>vmbr0</code>).</li>
<li>Start the iStoreOS VM.</li>
</ol>
<p>Ran the speed test again. Success! Speeds jumped right back up to the ~950 Mbps range. The virtualization bottleneck was eliminated.</p>
<h2 id="tailscale-triumph-conquering-remote-access">Tailscale Triumph: Conquering Remote Access</h2>
<p>My final major goal was setting up remote access, primarily to manage services like my NAS (planned OMV VM) and potentially the router itself when away from home. I opted for <strong>Tailscale</strong> due to its ease of use and availability in the iStoreOS app store.</p>
<p>Installation was simple. Following the command-line instructions (<code>tailscale up --advertise-routes=10.0.0.0/24</code>) connected the router to my Tailnet and advertised my home LAN subnet. However, while the router appeared online in the Tailscale admin console, I couldn&rsquo;t access <em>any</em> devices on my home LAN (like <code>10.0.0.1</code>) from my phone connected via Tailscale.</p>
<h3 id="troubleshooting-round-1-firewall">Troubleshooting Round 1: Firewall</h3>
<p>Pinging <code>10.0.0.1</code> from my phone resulted in &ldquo;Destination Port Unreachable.&rdquo; This screamed <strong>firewall</strong>. iStoreOS hadn&rsquo;t automatically created a firewall zone or rules for the new <code>tailscale0</code> interface.</p>
<h3 id="troubleshooting-round-2-interface--zone">Troubleshooting Round 2: Interface &amp; Zone</h3>
<p>Following guidance from GitHub issues, I manually edited <code>/etc/config/network</code> to define the <code>tailscale0</code> interface:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">config interface <span class="s1">&#39;tailscale&#39;</span>
</span></span><span class="line"><span class="cl">        option proto <span class="s1">&#39;none&#39;</span>
</span></span><span class="line"><span class="cl">        option device <span class="s1">&#39;tailscale0&#39;</span>
</span></span></code></pre></div><p>Then, in the LuCI Firewall settings (<code>Network -&gt; Firewall</code>), I:</p>
<ol>
<li>Created a new firewall zone named <code>tailscale</code>.</li>
<li>Set its Input/Output/Forward policies to <code>ACCEPT</code>.</li>
<li>Assigned the <code>tailscale0</code> network interface to this zone.</li>
<li>Crucially, created a <strong>Forwarding rule</strong> allowing traffic from the <code>tailscale</code> zone to the <code>lan</code> zone.</li>
</ol>
<p>Saved and applied. Tried connecting again. The &ldquo;Port Unreachable&rdquo; error was gone, but now attempts to access <code>10.0.0.1</code>just&hellip; hung. Loading indefinitely.</p>
<h3 id="troubleshooting-round-3-mtumss">Troubleshooting Round 3: MTU/MSS</h3>
<p>This new symptom – indefinite loading – strongly suggested an <strong>MTU (Maximum Transmission Unit)</strong> mismatch problem, common with VPNs and tunnels like Tailscale. Packets were likely getting fragmented or dropped because their size exceeded what the tunnel could handle. The standard fix is <strong>MSS Clamping (Maximum Segment Size)</strong>, where the router rewrites TCP packet headers to request smaller segment sizes.</p>
<h3 id="the-final-fix-iptables-mss-clamping">The Final Fix: iptables MSS Clamping</h3>
<p>Added the following rules via <code>Network -&gt; Firewall -&gt; Custom Rules</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Tailscale MSS Clamping for IPv4</span>
</span></span><span class="line"><span class="cl">iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Tailscale MSS Clamping for IPv6 (if using IPv6 with Tailscale)</span>
</span></span><span class="line"><span class="cl">ip6tables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</span></span></code></pre></div><p>Restarted the firewall. Tried accessing <code>10.0.0.1</code> from my phone via Tailscale one last time.</p>
<p><strong>Victory!</strong> The iStoreOS login page loaded instantly. Remote access was finally conquered.</p>
<h2 id="conclusion-a-system-forged-in-debugging">Conclusion: A System Forged in Debugging</h2>
<p>This journey, from a simple IPv6 issue to a fully virtualized N100 soft router with custom services and robust remote access, was far more challenging than I initially anticipated. Every step seemed to uncover a new problem, requiring deep dives into networking concepts, Linux internals, and virtualization quirks.</p>
<p>However, each problem solved solidified my understanding and resulted in a final system that is incredibly powerful, stable, and perfectly tailored to my needs. The N100 platform with Proxmox and iStoreOS has proven to be an outstanding foundation. The debugging war is over, and the era of enjoying a truly capable home lab has begun.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
