<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Alex King's blog</title><link>https://blog.hljin.net/en-us/</link><description>Recent content on Alex King's blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sun, 07 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.hljin.net/en-us/index.xml" rel="self" type="application/rss+xml"/><item><title>Deploying Headscale to Build a Private Tailscale Network</title><link>https://blog.hljin.net/en-us/2025/12/deploy-headscale/</link><pubDate>Sun, 07 Dec 2025 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2025/12/deploy-headscale/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>My private home network originally used Zerotier, but I found the connection to be unstable. Even when both of my nodes had public IPs, they sometimes failed to connect. Later I switched to WireGuard, which turned out to be very stable. Recently, however, I bought several new VPS instances and a friend’s home network also joined mine. The number of nodes increased, security rules became more complex, and maintaining WireGuard started to feel overwhelming. So I finally decided to deploy Headscale and migrate to a Tailscale-based network.&lt;/p></description></item><item><title>Fixing 'unable to install the EFI boot loader' when installing PVE</title><link>https://blog.hljin.net/en-us/2025/11/pve-efi-boot-loader/</link><pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2025/11/pve-efi-boot-loader/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>I recently bought a small J1900 mini PC to give to a friend as a soft router. As usual, I tried to install Proxmox on it, but ran into an issue I’d never seen before: when the progress bar reached 100%, it threw this error: &lt;code>failed to prepare EFI boot using Grub on '/dev/sda2': unable to install the EFI boot loader on '/dev/sda'&lt;/code>. I then spent the whole afternoon wrestling with it before finally fixing the problem.&lt;/p></description></item><item><title>OpenWrt Hardware Flow Offload Causing MAC Address Caching</title><link>https://blog.hljin.net/en-us/2025/11/flowtable-mac-issue/</link><pubDate>Tue, 18 Nov 2025 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2025/11/flowtable-mac-issue/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Ran into yet another pitfall. This time it happened when I tried to migrate my original Proxmox VM ImmortalWrt (a build of OpenWrt) into Docker while keeping the IP address unchanged. This ImmortalWrt instance is running my WireGuard service. The migration itself went smoothly. After starting the Docker container, ping worked fine, and my phone could connect to WireGuard. Only one always-on 24/7 node stubbornly refused to connect: no handshake, WireGuard showed 0 KB received, not a single packet came in.&lt;/p></description></item><item><title>Docker Bridging to Host Network</title><link>https://blog.hljin.net/en-us/2025/11/docker-host-bridge-network/</link><pubDate>Tue, 11 Nov 2025 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2025/11/docker-host-bridge-network/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>The subtitle of this post could be “My Hacky Docker Networking Setup”. It mainly describes the pitfalls I ran into when configuring Docker to bridge to the host network.&lt;/p>
&lt;p>Docker’s bridge network is an internal network; all communication with the outside world has to go through L3 routing and NAT, which is inconvenient for some applications. If you want to bridge to the host network, the simplest approach is to use macvlan. However, macvlan has the drawback that it cannot communicate with the host, so it’s not a perfect solution.&lt;/p></description></item><item><title>Kotlin Coroutine Pitfalls Record</title><link>https://blog.hljin.net/en-us/2023/10/kotlin-coroutine-mysteries/</link><pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2023/10/kotlin-coroutine-mysteries/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>I’ve been using Kotlin Coroutine in projects for more than a year. Although I’ve only used some very basic features, I still ran into plenty of pitfalls. This post records them as notes.&lt;/p></description></item><item><title>Installing DSM with libvirt</title><link>https://blog.hljin.net/en-us/2022/10/dsm-on-libvirt/</link><pubDate>Fri, 21 Oct 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/10/dsm-on-libvirt/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>After a recent NAS upgrade, I ended up with two spare 10 TB drives that I didn’t add to the array. I initially planned to use them for an additional ZFS backup, but later found out that zrepl doesn’t support multiple destinations, so I dropped the idea. Since I had just finished setting up WebVirtCloud, I figured I’d try running a black Synology (XPEnology), passthrough the two disks, and get another toy to play with.&lt;/p></description></item><item><title>Kotlin Coroutine Notes</title><link>https://blog.hljin.net/en-us/2022/04/kotlin-coroutine-note/</link><pubDate>Wed, 06 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/04/kotlin-coroutine-note/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>In the past two days I’ve been digging into how Kotlin coroutines work under the hood. I’ve read a lot of materials, and went from feeling completely lost to now having some rough intuition. This post records my current understanding of Kotlin coroutines.&lt;/p></description></item><item><title>Dockerfile Pitfalls</title><link>https://blog.hljin.net/en-us/2022/03/dockerfile-issues/</link><pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/03/dockerfile-issues/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Recently I’ve been writing Dockerfiles at work to build an image that contains a conda environment. I ran into countless pitfalls and can only lament my lack of skill; I’m recording them here.&lt;/p></description></item><item><title>Kodi Playback Stutter Caused by Samba Configuration</title><link>https://blog.hljin.net/en-us/2022/02/samba-kodi/</link><pubDate>Fri, 11 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/02/samba-kodi/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Recently, when watching &lt;em>The Good Doctor&lt;/em> with Kodi on my TV, the stuttering was so severe that it was basically unwatchable. At first I thought it was an issue with the source itself, maybe some highly compressed encoding parameters were used. I was quite puzzled though, because I had previously played HEVC 4K HDR videos without any issues, but I didn’t think too much of it. Later I found that almost all videos could no longer play normally, which clearly meant something had gone wrong somewhere, so I started another round of troubleshooting.&lt;/p></description></item><item><title>Enable TLS Connection for Docker Daemon</title><link>https://blog.hljin.net/en-us/2022/02/docker-daemon-tls/</link><pubDate>Thu, 10 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/02/docker-daemon-tls/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Background: The NAS uses a Xeon W-2140B CPU without an integrated GPU, and the onboard ASPEED graphics is essentially unusable for hardware acceleration, so Jellyfin cannot use hardware decoding. Although I tested that CPU software decoding can handle one 4K-to-4K transcoding stream smoothly, the CPU usage is already close to 100%. So I decided to move Jellyfin to an Ubuntu VM running on ESXi with a Core i3 8100T. To conveniently manage Docker on both machines, I want the Portainer instance running on the NAS to connect to the new Docker Daemon.&lt;/p></description></item><item><title>Fixing the Linksys Velop Red Status Light While Network Stays Fine</title><link>https://blog.hljin.net/en-us/2022/02/velop-red-issue/</link><pubDate>Sat, 05 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/02/velop-red-issue/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>During the earlier process of &lt;a href="https://blog.hljin.net/en-us/2022/02/iptv-proxy/">tinkering with IPTV&lt;/a>, I noticed that the status light on the Linksys Velop used as an AP turned red, but the network on my computer was completely fine. At first I thought it was caused by &lt;code>igmpproxy&lt;/code>, but later found that the issue remained even after stopping &lt;code>igmpproxy&lt;/code>. This post documents how I solved this problem.&lt;/p></description></item><item><title>Tinkering with IPTV on a PC</title><link>https://blog.hljin.net/en-us/2022/02/iptv-proxy/</link><pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2022/02/iptv-proxy/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>My dad recently retired and has nothing much to do at home. For some reason he’s started to enjoy watching multiple videos at the same time on his PC, and asked me if it’s possible to watch TV channels (mainly Five Star Sports) on the computer. I’d seen some public IPTV channel lists that can be played directly with Potplayer, and I also knew there are solutions to forward China Telecom’s IPTV to a PC, but since I don’t watch TV myself I never had the motivation to tinker with it. Recently I finally gave it a try.&lt;/p></description></item><item><title>A Docker DNS Troubleshooting Story</title><link>https://blog.hljin.net/en-us/2020/02/docker-dns-troubleshooting/</link><pubDate>Tue, 04 Feb 2020 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2020/02/docker-dns-troubleshooting/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>This afternoon a colleague came to me with a problem: a container couldn’t resolve domain names. I thought DNS issues wouldn’t be hard to fix… and then spent the next 8 hours troubleshooting.&lt;/p></description></item><item><title>BASH Concepts and Common Syntax</title><link>https://blog.hljin.net/en-us/2017/09/bash-concept-and-syntax/</link><pubDate>Sat, 30 Sep 2017 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2017/09/bash-concept-and-syntax/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>This article is a brief summary of the &lt;a href="https://www.gnu.org/software/bash/manual/bash.html">Bash Reference Manual&lt;/a>.&lt;/p></description></item><item><title>Effective Modern C++ Study Notes</title><link>https://blog.hljin.net/en-us/2016/06/effective-modern-cpp-excerpt/</link><pubDate>Tue, 14 Jun 2016 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2016/06/effective-modern-cpp-excerpt/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>This article contains some study notes from Effective Modern C++.&lt;/p></description></item><item><title>What the HELL is MEMORY MODEL</title><link>https://blog.hljin.net/en-us/2016/05/memory-model/</link><pubDate>Mon, 23 May 2016 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2016/05/memory-model/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>This title looks as if I were capable of answering this question. In fact, I’m not; I’m miles away from being able to answer it. This article is only a summary of the material I’ve read so far and my own understanding of it, with absolutely no guarantee of accuracy.&lt;/p></description></item><item><title>Recommending a Few Apps</title><link>https://blog.hljin.net/en-us/2016/04/suggest-app/</link><pubDate>Thu, 07 Apr 2016 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2016/04/suggest-app/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>I haven’t updated my blog for a long time. Since I don’t have the habit of keeping records, many times after solving a problem I’d think about writing it down to share, but then I’d feel that not many people would read it anyway, so I’d drop it. But ever since Gu Guofei forced me to read papers, I’ve realized that not taking notes doesn’t work: by the time I finish the next paper, I’ve already forgotten the previous one and can’t grasp the key points at all. I recently switched to an iPhone, and in order to improve efficiency I’ve tried a bunch of apps. I’ll recommend some of them here, and also talk a bit about the NAS I bought during last year’s Double 11.&lt;/p></description></item><item><title>Site Equipped with HTTPS and SPDY</title><link>https://blog.hljin.net/en-us/2015/03/equipped-with-https-and-spdy/</link><pubDate>Tue, 24 Mar 2015 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2015/03/equipped-with-https-and-spdy/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Using HTTPS is clearly the general trend; in the future all websites should adopt HTTPS encrypted connections to ensure security and privacy.&lt;/p>
&lt;p>All of Google’s sites have fully enabled HTTPS. According to Google, the overhead introduced by HTTPS is very small. However, in actual use the latency caused by the HTTPS handshake is still quite noticeable, especially when using HTTP/1.1, where multiple connections to the server are usually established and each one has to go through the HTTPS handshake.&lt;/p></description></item><item><title>Summary of Learning Regular Expressions</title><link>https://blog.hljin.net/en-us/2014/12/regular-expression/</link><pubDate>Sat, 13 Dec 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/12/regular-expression/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Most of my previous understanding of regular expressions came from scattered bits of knowledge. Often, when I needed to use some regular expression and forgot how to write it, I would look it up on this &lt;a href="http://deerchao.net/tutorials/regex/regex.htm">page&lt;/a>. Last time, when helping dhl solve a problem of extracting strings of the form &lt;code>http://xxx.jpg&lt;/code> from HTML, after a series of frustrations, I decided to properly study regular expressions. I bought the book “Mastering Regular Expressions” during the Double 11 sale. I’ve read five chapters so far, hence this short summary.&lt;/p></description></item><item><title>Importing Packets into the Protocol Stack with tun/tap</title><link>https://blog.hljin.net/en-us/2014/10/use-tun-tap/</link><pubDate>Wed, 22 Oct 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/10/use-tun-tap/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>I originally thought the reason the dorm PC couldn’t ping the lab PC was that there was a layer of NAT in between. After talking with Wu Bo yesterday, I realized there was actually no NAT; it was a firewall issue. The firewall should be dropping ICMP packets and all inbound &lt;code>TCP SYN&lt;/code> packets, so an external machine cannot establish a TCP connection directly to the lab machine. After some discussion with Wu Bo, I got the idea to try to break through the restriction that the dorm machine cannot establish TCP connections to the lab machine.&lt;/p></description></item><item><title>Compiling Wireshark on Windows</title><link>https://blog.hljin.net/en-us/2014/10/compile-wireshark/</link><pubDate>Mon, 20 Oct 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/10/compile-wireshark/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>The project I was working on used the IP header Option field and defined a custom type. By default Wireshark shows this as Unknown. To make the demo look better, I added some code to let Wireshark support custom Option types. Since this is not a standalone protocol, it cannot be extended with Lua and similar mechanisms, so Wireshark has to be recompiled. Compilation on Linux is very simple, but on Windows it is much more cumbersome, hence this article.&lt;/p></description></item><item><title>autotools Tinkering Notes</title><link>https://blog.hljin.net/en-us/2014/10/autotools-play/</link><pubDate>Fri, 10 Oct 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/10/autotools-play/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>It’s time again for that painful-yet-joyful tinkering, and this time the target is autotools. Back in the day I used to admire the &lt;code>configure&lt;/code> and &lt;code>Makefile&lt;/code> files in various open-source projects. I naively thought they were all handwritten by the project authors themselves, and I was full of awe for people in the open-source community. I couldn’t even understand them, let alone write them. Later I learned there is something called &lt;code>autoconf&lt;/code> that can automatically generate these scripts. You still have to write some bits yourself, but it’s nowhere near as crazy as I had imagined.&lt;/p></description></item><item><title>Cross-Compiling an ARM Native GCC</title><link>https://blog.hljin.net/en-us/2014/09/cross-compile-arm-natvie-gcc/</link><pubDate>Wed, 10 Sep 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/09/cross-compile-arm-natvie-gcc/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Some time ago I learned to use IP tunnel to build a tunnel so that machines without native IPv6 could use IPv6. I was itching to get IPv6 at home in advance as well, so I finally bit the bullet and bought the R6300v2 I’d been eyeing for a long time. With ddwrt on it, IPv6 worked smoothly.&lt;/p></description></item><item><title>Settle Down</title><link>https://blog.hljin.net/en-us/2014/09/settle-down/</link><pubDate>Tue, 09 Sep 2014 00:00:00 +0000</pubDate><guid>https://blog.hljin.net/en-us/2014/09/settle-down/</guid><description>&lt;div class="alert warning ">
&lt;p>This article is translated from Chinese to English by ChatGPT. There might be errors.&lt;/p>
&lt;/div>
&lt;p>Back when I first started playing with VPS, I set up a blog, but abandoned it after writing only a few posts. Blogs are more suitable for technical articles; if I post about my feelings, who would come back to read them? But every time I finish tinkering with something, I feel exhausted. It’s really “tinkering”: I always run into all sorts of strange problems, and then I don’t feel like writing anymore. So how long I can keep this blog going, I honestly have no idea. Of course, I was also influenced by wjx. That guy has been really into blogging recently, doing it with great flair, &lt;a href="http://devopstarter.info">link here&lt;/a>, which got me wanting to do it as well.&lt;/p></description></item></channel></rss>