<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Home-Lab on Margrop Blog</title>
    <link>https://blog.margrop.net/en/tag/home-lab/</link>
    <description>Recent content in Home-Lab on Margrop Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <lastBuildDate>Sun, 05 Jul 2026 06:50:00 +0800</lastBuildDate>
    <atom:link href="https://blog.margrop.net/en/tag/home-lab/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Stop Fighting Over the Remote: Use DSM Scheduled Tasks to Lock a Kids&#39; Video Folder Automatically</title>
      <link>https://blog.margrop.net/en/post/synology-kid-video-acl-curfew/</link>
      <pubDate>Sun, 05 Jul 2026 06:50:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/synology-kid-video-acl-curfew/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;This is not an account lockout guide. The goal is narrower and cleaner: lock one kids&amp;rsquo; video folder on a Synology DSM 7.2.1 NAS during selected hours, while leaving the account, password, homework folders, photo folders, and other shares alone. The script inserts one temporary &lt;code&gt;deny&lt;/code&gt; ACL entry with &lt;code&gt;synoacltool&lt;/code&gt;, removes that entry during open windows, backs up the ACL before each change, and verifies the result after each operation.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;Original cover: the kids&amp;rsquo; video folder is locked by schedule&#34; src=&#34;https://blog.margrop.net/post-images/synology-kid-video-acl-curfew/00-ai-cover.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>One sentence let Claude upgrade Ubuntu 22.04 to 24.04: a near-zero-screen-time cross-LTS run</title>
      <link>https://blog.margrop.net/en/post/upgrade-ubuntu-via-agent/</link>
      <pubDate>Fri, 19 Jun 2026 10:58:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/upgrade-ubuntu-via-agent/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;A remote home-lab box had been sitting on Ubuntu 22.04.4 LTS (jammy, kernel 5.15) for a long time. After one sentence — &amp;ldquo;upgrade the box at 192.168.103.182 to Ubuntu 24.04&amp;rdquo; — Claude opened a tmux session to babysit the run, brought up a fallback sshd on port 1022 so a mid-upgrade sshd restart would not strand me, then drove &lt;code&gt;do-release-upgrade -f DistUpgradeViewNonInteractive&lt;/code&gt; end to end. Twenty-five minutes later the host came back: kernel 6.8.0-124, every service still listening.&lt;/p&gt;&#xA;&lt;p&gt;This is not a tutorial on &lt;code&gt;do-release-upgrade&lt;/code&gt;; the Ubuntu docs already cover that. This is about what an Agent does once it gets an SSH handle on a box, why it does each step, and which pitfalls you have to clear out of the way before letting it loose.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Ubuntu shutdown stuck for 90 seconds? A Python asyncio service that won&#39;t honour SIGTERM, and how to fix it</title>
      <link>https://blog.margrop.net/en/post/ubuntu-shutdown-stuck/</link>
      <pubDate>Fri, 19 Jun 2026 10:58:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/ubuntu-shutdown-stuck/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;After upgrading my home proxy box to Ubuntu 24.04, &lt;code&gt;systemctl reboot&lt;/code&gt; stopped being fast: SSH would hang on for &lt;strong&gt;90 seconds&lt;/strong&gt; before the box actually shut down. &lt;code&gt;journalctl&lt;/code&gt; made it obvious: &lt;code&gt;smart-proxy.service: State &#39;stop-sigterm&#39; timed out. Killing.&lt;/code&gt; — systemd sent SIGTERM, waited 90 seconds, nobody reacted, and SIGKILL was the only option left.&lt;/p&gt;&#xA;&lt;p&gt;The root cause is not systemd&amp;rsquo;s fault and not Ubuntu&amp;rsquo;s fault. It is &lt;strong&gt;Python&amp;rsquo;s asyncio runtime not actually ending its child tasks when SIGTERM arrives&lt;/strong&gt; — it is parked on a &lt;code&gt;socket.recv&lt;/code&gt; and never voluntarily looks at the signal queue.&lt;/p&gt;&#xA;&lt;p&gt;The fix has two halves, both required: &lt;strong&gt;(1)&lt;/strong&gt; a systemd drop-in that lowers &lt;code&gt;TimeoutStopSec&lt;/code&gt; from the default 90s down to 20s on the affected Python units; &lt;strong&gt;(2)&lt;/strong&gt; inside the Python service itself, walk &lt;code&gt;asyncio.all_tasks()&lt;/code&gt;, &lt;code&gt;.cancel()&lt;/code&gt; the in-flight connection handlers on SIGTERM, and wrap &lt;code&gt;self.stop()&lt;/code&gt; in &lt;code&gt;asyncio.wait_for(..., timeout=10)&lt;/code&gt; as a safety net. After both halves, the same &lt;code&gt;reboot&lt;/code&gt; drops from 90 seconds to one second.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Synology locked root behind three doors — I spent twenty minutes teaching it how to let me back in</title>
      <link>https://blog.margrop.net/en/post/synology-root-and-ssh-key/</link>
      <pubDate>Thu, 18 Jun 2026 16:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/synology-root-and-ssh-key/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Synology DSM, by design, ships with SSH &lt;strong&gt;disabled&lt;/strong&gt; and root login &lt;strong&gt;prohibited&lt;/strong&gt; — both sensible defaults. This guide walks you through &amp;ldquo;doing it the right way&amp;rdquo;:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Control Panel → Terminal &amp;amp; SNMP → Enable SSH&lt;/strong&gt; (open the gate)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Log in as a normal user, then &lt;code&gt;sudo -i&lt;/code&gt; to become root&lt;/strong&gt; (borrow the landlord&amp;rsquo;s key first)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Edit &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and set &lt;code&gt;PermitRootLogin yes&lt;/code&gt;&lt;/strong&gt; (tell the bouncer &amp;ldquo;root is family&amp;rdquo;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;synouser --setpw root xxx&lt;/code&gt; to set a root password, and append your public key to &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;&lt;/strong&gt; (hand back a key that can never be lost)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Total time: about twenty minutes. I&amp;rsquo;ll explain &lt;em&gt;why&lt;/em&gt; every step exists using a &amp;ldquo;key and lock&amp;rdquo; metaphor, give you a 3-second vi crash course, list the error messages you&amp;rsquo;ll see, and answer the seven most common questions.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>I dockerized AnythingLLM and the container turned into a wound-up squirrel — restarting forever until I handed it that magic 1000:1000</title>
      <link>https://blog.margrop.net/en/post/anythingllm-docker-deploy/</link>
      <pubDate>Wed, 17 Jun 2026 20:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/anythingllm-docker-deploy/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;AnythingLLM, Mintplex Labs&amp;rsquo; &amp;ldquo;stuff-anything-in-a-LLM&amp;rdquo; desktop, ships an official Docker image. In the happy path one &lt;code&gt;docker run&lt;/code&gt; is all you need. But the in-container user &lt;code&gt;anythingllm&lt;/code&gt; is picky: the host directory you bind-mount has to be owned by &lt;code&gt;1000:1000&lt;/code&gt;, otherwise it can&amp;rsquo;t write its own SQLite file, the Prisma migration step on startup crashes, and the container enters a &lt;em&gt;restart-crash-restart&lt;/em&gt; loop. The fix takes under a minute: &lt;code&gt;chown -R 1000:1000 /your/data/dir&lt;/code&gt;, then &lt;code&gt;docker compose up -d&lt;/code&gt; again, and it dutifully listens on &lt;code&gt;3001&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll also explain why Prisma&amp;rsquo;s &lt;code&gt;file:../storage/anythingllm.db&lt;/code&gt; relative path is a footgun, give you a Portainer-ready stack file, and finish with a Q&amp;amp;A on the most common gotchas.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Home Network 1000Mbps but Games Stutter? A Complete Guide to Diagnosing and Fixing Bufferbloat</title>
      <link>https://blog.margrop.net/en/post/bufferbloat-sqm-cake-home-network-fix/</link>
      <pubDate>Sat, 30 May 2026 09:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/bufferbloat-sqm-cake-home-network-fix/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;The Short Version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Your router has a hidden enemy called &lt;strong&gt;Bufferbloat&lt;/strong&gt; — and it&amp;rsquo;s likely the reason your games lag even when your bandwidth test shows perfect speeds. When a router buffers too aggressively, download traffic fills up the queue and real-time traffic (games, video calls) gets stuck waiting behind thousands of buffered packets. Your speedtest stays at 950Mbps, but your game ping explodes from 50ms to 500ms.&lt;/p&gt;&#xA;&lt;p&gt;In this article, I walk through the complete diagnosis and resolution of a Bufferbloat problem in a real home network environment using a multi-WAN iKuai gateway + ImmortalWrt soft router setup. The fix: deploying &lt;strong&gt;SQM (Smart Queue Management) + Cake qdisc&lt;/strong&gt; on the ImmortalWrt layer, which reduced latency under full-speed download from ~300ms+ down to a stable ~12ms with zero configuration complexity.&lt;/p&gt;&#xA;&lt;p&gt;All internal IP addresses, device hostnames, and network topologies have been sanitized for privacy.&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>After Buying a Domain, Use Cloudflare Tunnel to Turn Home Services into Public HTTPS</title>
      <link>https://blog.margrop.net/en/post/cloudflare-tunnel-public-https-no-public-ip/</link>
      <pubDate>Thu, 21 May 2026 11:38:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/cloudflare-tunnel-public-https-no-public-ip/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The previous two posts covered the cheap-domain part and the Cloudflare DNS part: buy a low-cost &lt;code&gt;.xyz&lt;/code&gt; domain for personal lab use, then move the domain to Cloudflare for nameservers, DNS, DDNS, email routing, and basic automation. This post continues with the next practical step: use Cloudflare Tunnel to expose an internal web service as a public &lt;code&gt;https://&lt;/code&gt; hostname. The important point is that visitors use standard HTTPS on port 443, while your home router does not need to forward ports 80 or 443 and your origin IP does not need to be exposed.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This article follows these two posts:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;“Ten Years for 80 Yuan: Why I Prefer 6-Digit &lt;code&gt;.xyz&lt;/code&gt; Domains for Personal Sites”&lt;br&gt;&#xA;Original link: &lt;a href=&#34;https://mp.weixin.qq.com/s/tbefnWGFI0QBFlRVcYjVEw&#34;&gt;https://mp.weixin.qq.com/s/tbefnWGFI0QBFlRVcYjVEw&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;“Do Not Waste That 80-Yuan Ten-Year Domain: Put It on Cloudflare First”&lt;br&gt;&#xA;Original link: &lt;a href=&#34;https://mp.weixin.qq.com/s/h0o-vtGB_zj1aptaumBztQ&#34;&gt;https://mp.weixin.qq.com/s/h0o-vtGB_zj1aptaumBztQ&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Those posts already covered buying a cheap &lt;code&gt;.xyz&lt;/code&gt; domain, moving nameservers to Cloudflare, creating DNS records, using DDNS, and setting up email-related records. This post assumes that your domain is already active on Cloudflare. We will focus on one thing: publishing an internal web service through Cloudflare Tunnel with a clean public HTTPS hostname.&lt;/p&gt;&#xA;&lt;p&gt;All examples in this article use documentation placeholders such as &lt;code&gt;example.xyz&lt;/code&gt;, &lt;code&gt;nas.speedtest.example.xyz&lt;/code&gt;, &lt;code&gt;192.0.2.10&lt;/code&gt;, &lt;code&gt;localhost&lt;/code&gt;, and &lt;code&gt;&amp;lt;TUNNEL_TOKEN&amp;gt;&lt;/code&gt;. No real domain, account, token, zone ID, private network address, or personal information is included.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ten Years for 80 Yuan: Why a 6-Digit .xyz Domain Is Good Enough for Personal Labs</title>
      <link>https://blog.margrop.net/en/post/low-cost-xyz-domain-for-personal-labs/</link>
      <pubDate>Tue, 12 May 2026 19:10:00 +0800</pubDate>
      <guid>https://blog.margrop.net/en/post/low-cost-xyz-domain-for-personal-labs/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Short version&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;If the domain is for a home lab, personal testing, temporary demos, API callbacks, development services, or other non-formal websites, I would first look at low-cost &lt;code&gt;.xyz&lt;/code&gt; domains. In China, Tencent Cloud often makes this especially convenient for domestic users. For some pure numeric &lt;code&gt;.xyz&lt;/code&gt; names with six or more digits, the checkout page may show a very low first-year and renewal price. If the price is 8 RMB per year, buying 10 years costs only 80 RMB.&lt;/p&gt;&#xA;&lt;p&gt;This is not a recommendation for company websites, public products, serious brands, payment systems, or long-term marketing pages. For those, a readable and trustworthy brand domain is still worth the money.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;When people start building a personal website, home lab, NAS callback endpoint, temporary API, reverse proxy, monitoring page, or small side project, they often overthink the domain name. Should it be a &lt;code&gt;.com&lt;/code&gt;? Should it be short? Should it look like a real company? Should it use pinyin, English words, initials, or a private nickname?&lt;/p&gt;&#xA;&lt;p&gt;My practical answer is: first decide what the domain is supposed to do.&lt;/p&gt;&#xA;&lt;p&gt;If it is a serious public identity, choose the name carefully. If it is just a personal utility domain, do not spend too much money or attention on the name. In that case, the domain is not a brand asset. It is a stable handle for DNS, HTTPS, reverse proxy rules, ACME certificates, third-party callbacks, object storage, and temporary services.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
