<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Igor Bubelov</title>
        <link>https://bubelov.com/tags/protocols/</link>
        <description>All posts by Igor Bubelov</description><atom:link href="https://bubelov.com/tags/protocols/index.xml" rel="self" type="application/rss+xml" />
        <item>
            <title>Core Lightning Post Mortem</title>
            <link>https://bubelov.com/blog/2026/cln/</link>
            <pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/cln/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#the-old-setup&#34;&gt;The Old Setup&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#the-cln-shenanigans&#34;&gt;The CLN Shenanigans&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#the-dynamic-linking-problem&#34;&gt;The Dynamic Linking Problem&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#lnd-gets-it-right&#34;&gt;LND Gets It Right&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#the-counterarguments&#34;&gt;The Counterarguments&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#what-i-miss&#34;&gt;What I Miss&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;the-old-setup&#34;&gt;The Old Setup&lt;/h2&gt;
&lt;p&gt;I set up BTC Map&amp;rsquo;s first Lightning node in late 2022, and I picked CLN, mostly because it was ahead of the curve on BOLT-12 adoption. Installing &lt;code&gt;lightningd&lt;/code&gt; wasn&amp;rsquo;t easy, though. It only officially supports Ubuntu, and BTC Map&amp;rsquo;s fleet runs on Arch.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s take a closer look at the CLN package.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar --extract --file clightning-v24.08.1-Ubuntu-24.04.tar.xz --verbose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-cln-shenanigans&#34;&gt;The CLN Shenanigans&lt;/h2&gt;
&lt;p&gt;What follows is a complete explosion of files. Dozens of binaries, plugins, Python scripts, documentation, and even &lt;code&gt;.github&lt;/code&gt; folders with screenshots, shipped accidentally inside the package.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve trimmed the output, but the picture is clear:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/bin/lightning-cli
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/bin/lightning-hsmtool
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/bin/lightningd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/bin/reckless
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_channeld
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_closingd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_connectd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_dualopend
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_gossipd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_hsmd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_onchaind
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_openingd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/lightning_websocketd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/autoclean
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/bcli
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/bookkeeper
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/chanbackup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/cln-askrene
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/cln-grpc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/cln-renepay
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Postman-bkpr-plugin.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Postman-with-body.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Postman.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Swagger-auth.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Swagger-list-methods.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Swagger-rpc-method.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/.github/screenshots/Swagger.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/Makefile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/__init__.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/clnrest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/clnrest.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/poetry.lock
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/pyproject.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/__init__.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/generate_certs.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/rpc_plugin.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/rpc_routes.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/clnrest/utilities/shared.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/commando
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/funder
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/keysend
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/offers
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/pay
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/recklessrpc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/recover
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/spenderp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/sql
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/topology
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/txprepare
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/Makefile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/poetry.lock
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/pyproject.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/wss-proxy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/wss-proxy.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/wss_proxy/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/libexec/c-lightning/plugins/wss-proxy/wss_proxy/__init__.py
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/doc/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/doc/c-lightning/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/doc/c-lightning/LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/doc/c-lightning/README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./usr/share/man/... &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;OMITTED&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is complete insanity. Usually, you just need a single binary, like &lt;code&gt;bitcoind&lt;/code&gt;, and you&amp;rsquo;re done. But CLN takes an unorthodox approach: instead of one self-contained executable, you get dozens of moving parts glued together in weird ways.&lt;/p&gt;
&lt;p&gt;Core Lightning is a maintenance nightmare.&lt;/p&gt;
&lt;h2 id=&#34;the-dynamic-linking-problem&#34;&gt;The Dynamic Linking Problem&lt;/h2&gt;
&lt;p&gt;It gets worse. For reference, Bitcoin Core binaries work on virtually any Linux system because they&amp;rsquo;re statically linked. I expected the same from CLN, but no. CLN relies heavily on dynamic linking, which means it makes bold assumptions about the host environment.&lt;/p&gt;
&lt;p&gt;My last attempt at updating CLN failed because the system had a newer version of &lt;code&gt;libsodium&lt;/code&gt; or something like that, it adds completely unnecessary friction and a constant source of uncertainty.&lt;/p&gt;
&lt;p&gt;Combine that with the convoluted packaging, and you get the least sane Lightning implementation I&amp;rsquo;ve ever dealt with.&lt;/p&gt;
&lt;h2 id=&#34;lnd-gets-it-right&#34;&gt;LND Gets It Right&lt;/h2&gt;
&lt;p&gt;LND, on the other hand, is almost perfect. It follows the &lt;code&gt;bitcoind&lt;/code&gt; playbook to the letter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar --extract --file lnd-linux-amd64-v0.20.0-beta.tar.gz --verbose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lnd-linux-amd64-v0.20.0-beta/lnd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lnd-linux-amd64-v0.20.0-beta/lncli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it. Two binaries. No hacky plugins, no screenshots, no sprawling directory trees, no Python dependencies, no &lt;code&gt;.github&lt;/code&gt; folders.&lt;/p&gt;
&lt;p&gt;Check the dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ldd lnd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;not a dynamic executable
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Statically linked. Self-contained. Upgrade is a simple file swap. This is the only deployment pattern that makes sense for a decentralized network with a huge number of self-hosted nodes.&lt;/p&gt;
&lt;h2 id=&#34;the-counterarguments&#34;&gt;The Counterarguments&lt;/h2&gt;
&lt;p&gt;Of course, there are always Ubuntu maxis and the Docker crowd, ready to sell you their &amp;ldquo;solutions&amp;rdquo; while conveniently ignoring the baggage such as invasive abstraction layers and all the extra complexity.&lt;/p&gt;
&lt;h2 id=&#34;what-i-miss&#34;&gt;What I Miss&lt;/h2&gt;
&lt;p&gt;The one thing LND still lacks is full BOLT-12 support, and that&amp;rsquo;s the only reason I originally chose CLN. In practice, though, BOLT-11 has stayed relevant far longer than I expected and it will keep being a reasonable default option for the years to come. BOLT-12 development is progressing slowly but steadily, and we&amp;rsquo;ll get there eventually.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re running a Lightning node and value your sanity, pick LND. It&amp;rsquo;s the only implementation that aims to be usable.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wireless Charging</title>
            <link>https://bubelov.com/blog/2026/wireless/</link>
            <pubDate>Sun, 08 Feb 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/wireless/</guid>
            <description>&lt;h2 id=&#34;the-accident&#34;&gt;The Accident&lt;/h2&gt;
&lt;p&gt;It all started with a deep clean. Buried in a tangle of old cables, I found a dusty wireless charger I&amp;rsquo;d completely forgotten about, a &amp;ldquo;Mi Wireless Charger&amp;rdquo;. I have no idea where it came from.&lt;/p&gt;
&lt;p&gt;On a whim, I dropped my Google Pixel 6 onto it. To my surprise, the screen lit up: &amp;ldquo;&lt;strong&gt;Charging Wirelessly&lt;/strong&gt;&amp;rdquo;. My power meter showed a solid 4W flowing into the phone, occasionally bumping up to 5W. Not exactly fast-charging, but for a forgotten gadget, it was above my expectations.&lt;/p&gt;
&lt;p&gt;That got me curious. This old thing was using the Qi standard, something I&amp;rsquo;d known about for years but never really paid attention to. Had it gotten any better over time? And were there newer, faster options out there now?&lt;/p&gt;
&lt;h2 id=&#34;the-wpc&#34;&gt;The WPC&lt;/h2&gt;
&lt;p&gt;A quick dive into the standard revealed the orchestrator: the &lt;strong&gt;Wireless Power Consortium (WPC)&lt;/strong&gt;. This isn&amp;rsquo;t a shadowy cabal, but an open alliance of hundreds of companies, from Apple to Xiaomi, that agreed on one crucial thing: ending the cord war.&lt;/p&gt;
&lt;p&gt;Before Qi, wireless charging was a mess of incompatible pads and proprietary tech. The WPC&amp;rsquo;s mission was to create a single, global standard. Their success is the only reason that old, forgotten pad could still charge my relatively modern phone. It&amp;rsquo;s a rare and beautiful case of industry cooperation that actually benefited users.&lt;/p&gt;
&lt;p&gt;The WPC hasn&amp;rsquo;t been idle, though. The standard evolved, and today &lt;strong&gt;Qi2&lt;/strong&gt;, the next generation with magnetic alignment, is finally taking off.&lt;/p&gt;
&lt;h2 id=&#34;magnets&#34;&gt;Magnets&lt;/h2&gt;
&lt;p&gt;The big improvement in Qi2 isn&amp;rsquo;t just raw speed, it&amp;rsquo;s alignment. And now I understand why my old pad was so flaky, bouncing between 4W and 5W.&lt;/p&gt;
&lt;p&gt;The new &lt;strong&gt;Magnetic Power Profile (MPP)&lt;/strong&gt; borrows the best idea from Apple&amp;rsquo;s MagSafe: built-in ring magnets. Suddenly, all the side effects of misalignment go away: the slight buzzing, the flickering light, the heat buildup as the charger tries and fails to lock on.&lt;/p&gt;
&lt;p&gt;Magnets solve that. Perfect alignment means more efficient power transfer, so charging is not only faster, but also noticeably cooler.&lt;/p&gt;
&lt;p&gt;A nice bonus: now that alignment is guaranteed, manufacturers are getting creative with angles. You can find magnetic chargers that hold your phone at 30° or 45°, turning your phone into a handy video screen while it powers up.&lt;/p&gt;
&lt;h2 id=&#34;the-bridge-to-the-old-world&#34;&gt;The Bridge to the Old World&lt;/h2&gt;
&lt;p&gt;The problem is, my Pixel 6 isn&amp;rsquo;t getting a Qi2 update cuz it&amp;rsquo;s a hardware limitation, not a software patch. The only way to upgrade is to buy a new phone, like a Pixel 10, and I&amp;rsquo;m not ready for that. I plan to keep using my Pixel 6 for another year, or at least until the battery gives out.&lt;/p&gt;
&lt;p&gt;Even so, I think getting a Qi2 charger now is still a smart move. You can buy a phone case with a strong magnetic ring built in, which gives you most of the alignment benefits of Qi2 without needing a new phone. It&amp;rsquo;s a perfect bridge between the old standard and the new one.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Curiosity won. I ordered a Qi2 charger from Ugreen.&lt;/p&gt;
&lt;p&gt;Qi was a great foundation, and Qi2 builds on it by finally fixing the frustrating user experience.&lt;/p&gt;
&lt;p&gt;This all started with a dusty old Qi pad I&amp;rsquo;d completely forgotten about. That accidental find sent me down a rabbit hole that ended with a much better charging setup. It was a good reminder that sometimes the best tech upgrades aren&amp;rsquo;t about raw speed, but about a simple, satisfying snap that just makes everything work better.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wi-Fi is the Best Protocol for Smart Lights</title>
            <link>https://bubelov.com/blog/2026/wifi-lights/</link>
            <pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/wifi-lights/</guid>
            <description>&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/wifi-lights/og_hu_89ad655f74cf8958.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/wifi-lights/og_hu_508e116b12ee0e24.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve had lights you can actually control (brightness, color, scheduling and all the other stuff), there&amp;rsquo;s zero chance you&amp;rsquo;re going back to the dumb ones. The whole smart light scene is a total mess though, because it&amp;rsquo;s split between Bluetooth, Zigbee, Wi-Fi, Matter over Thread, and Matter over Wi-Fi.&lt;/p&gt;
&lt;p&gt;I have a bunch of Wi-Fi lights (Philips WiZ) and a whole zoo of Zigbee lights, from premium Philips Hue all the way down to no-name AliExpress brands for $3. In practice, I like my Wi-Fi WiZ lights much more.&lt;/p&gt;
&lt;p&gt;While meshes like Zigbee and Thread are pitched as the best choice because every new device supposedly strengthens your network, most homes don&amp;rsquo;t actually need a mesh. In reality, it just adds trouble. This isn&amp;rsquo;t just my take; it&amp;rsquo;s &lt;a href=&#34;https://www.home-assistant.io/connect/zbt-2/&#34;&gt;basically how the industry is evolving&lt;/a&gt;. Zigbee coordinators are quickly moving from tiny USB sticks to giant dildos, centralizing the network around a single powerful node.&lt;/p&gt;
&lt;p&gt;Another serious flaw in Zigbee is letting lights act as router nodes instead of end nodes. When a router node goes offline, which happens anytime someone uses a physical light switch to cut its power, it disrupts the whole network. Zigbee networks do self-heal, but it takes time and makes the whole network slower and less predictable.&lt;/p&gt;
&lt;p&gt;Finding a good alternative isn&amp;rsquo;t easy. Bluetooth has range issues, and &amp;ldquo;naked&amp;rdquo; Wi-Fi lacks a standardized pairing and device-control protocol, so you end up needing a special app for every vendor, which is a hard no.&lt;/p&gt;
&lt;p&gt;While I don&amp;rsquo;t recommend &amp;ldquo;naked&amp;rdquo; Wi-Fi, a lot of the newer Wi-Fi lights do support a protocol called Matter. It acts as a common language between Wi-Fi devices and smart home hubs. Since they all speak it, you don&amp;rsquo;t need any vendor apps, and using physical switches won&amp;rsquo;t break your network.&lt;/p&gt;
&lt;p&gt;That said, Zigbee and Thread mesh networks aren&amp;rsquo;t going anywhere; there&amp;rsquo;s no real alternative for battery-powered devices such as sensors and buttons that need to have extremely low power draw to be usable. But for everything that plugs into the wall, I prefer Matter over Wi-Fi.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>$4 Zigbee Lightbulb Deep Dive</title>
            <link>https://bubelov.com/blog/2025/ali-lightbulb/</link>
            <pubDate>Wed, 01 Oct 2025 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2025/ali-lightbulb/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#intro&#34;&gt;Intro&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#node-descriptor&#34;&gt;Node Descriptor&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#logical-type&#34;&gt;Logical Type&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#complex-descriptor-available&#34;&gt;Complex Descriptor Available&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#user-descriptor-available&#34;&gt;User Descriptor Available&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#reserved&#34;&gt;Reserved&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#aps-flags&#34;&gt;APS Flags&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#frequency-band&#34;&gt;Frequency Band&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#medium-access-control-capability-flags&#34;&gt;Medium Access Control Capability Flags&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#manufacturer-code&#34;&gt;Manufacturer Code&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maximum-buffer-size&#34;&gt;Maximum Buffer Size&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maximum-incoming-transfer-size&#34;&gt;Maximum Incoming Transfer Size&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#server-mask&#34;&gt;Server Mask&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maximum-outgoing-transfer-size&#34;&gt;Maximum Outgoing Transfer Size&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#descriptor-capability-field&#34;&gt;Descriptor Capability Field&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#endpoint-1-of-1&#34;&gt;Endpoint 1 of 1&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#profile-id&#34;&gt;Profile ID&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#device-type&#34;&gt;Device Type&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#input-clusters&#34;&gt;Input Clusters&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#output-clusters&#34;&gt;Output Clusters&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#manufacturer&#34;&gt;Manufacturer&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#model&#34;&gt;Model&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#class&#34;&gt;Class&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;So, my first Zigbee bulbs were a bunch of Philips Hues. I snagged a pretty good deal on the bundle, they were still pricey even with the discount. I was expecting top-notch quality, but two of them kicked the bucket in under two years, which got me looking for other options.&lt;/p&gt;
&lt;p&gt;The first (and only) alternative I&amp;rsquo;ve tried is this &lt;code&gt;eWeLink&lt;/code&gt; model &lt;code&gt;CK-BL702-AL-01(7009_Z102LG03-1)&lt;/code&gt;. Yeah, the name sounds kinda scary, but they were only four bucks each on AliExpress. I ordered six of them to swap out the old Philips WiZ WiFi downlights in my kitchen.&lt;/p&gt;
&lt;p&gt;The lights showed up surprisingly fast and they were all working perfectly. Pairing them with Home Assistant was a breeze, they just worked with the standard Zigbee 3.0 pairing, no funny business.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s take a look at the Zigbee signature for these lights:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;node_descriptor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;logical_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;complex_descriptor_available&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;user_descriptor_available&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;reserved&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;aps_flags&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;frequency_band&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;mac_capability_flags&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;142&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;manufacturer_code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4742&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;maximum_buffer_size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;127&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;maximum_incoming_transfer_size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;242&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;server_mask&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;11264&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;maximum_outgoing_transfer_size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;242&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;descriptor_capability_field&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;endpoints&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;profile_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0104&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;device_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x010d&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;input_clusters&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0003&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0004&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0005&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0006&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0008&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0300&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0xef00&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0xfc11&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0xfc57&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;output_clusters&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;0x0019&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;manufacturer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;eWeLink&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;CK-BL702-AL-01(7009_Z102LG03-1)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;class&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zigpy.device.Device&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;node-descriptor&#34;&gt;Node Descriptor&lt;/h2&gt;
&lt;h3 id=&#34;logical-type&#34;&gt;Logical Type&lt;/h3&gt;
&lt;p&gt;Logical Type set to &lt;code&gt;1&lt;/code&gt; means these lights are Zigbee Routers, which is great news. Routers help extend your network&amp;rsquo;s range and make it more reliable.&lt;/p&gt;
&lt;p&gt;There is a debate about lightbulbs though, since those can be turned off with a physical switch, potentially disturbing the network. I would prefer downlights being leaf nodes.&lt;/p&gt;
&lt;h3 id=&#34;complex-descriptor-available&#34;&gt;Complex Descriptor Available&lt;/h3&gt;
&lt;p&gt;This device doesn&amp;rsquo;t have a complex descriptor, which is totally normal. Most devices skip this.&lt;/p&gt;
&lt;h3 id=&#34;user-descriptor-available&#34;&gt;User Descriptor Available&lt;/h3&gt;
&lt;p&gt;This is different from the complex descriptor, it&amp;rsquo;s meant for storing a custom label on the device itself. It&amp;rsquo;s empty here, which is standard if you&amp;rsquo;ve never set one. I don&amp;rsquo;t think Home Assistant even lets you edit this field right now anyway.&lt;/p&gt;
&lt;p&gt;HA&amp;rsquo;s own labeling system is way more flexible, since it&amp;rsquo;s not limited to a measly 16 characters like this Zigbee field.&lt;/p&gt;
&lt;h3 id=&#34;reserved&#34;&gt;Reserved&lt;/h3&gt;
&lt;p&gt;This is just an unused field saved for future features, so &lt;code&gt;0&lt;/code&gt; is exactly what we&amp;rsquo;d expect.&lt;/p&gt;
&lt;h3 id=&#34;aps-flags&#34;&gt;APS Flags&lt;/h3&gt;
&lt;p&gt;The Application Support Sub-layer (APS) flags are all zeros, which is pretty common.&lt;/p&gt;
&lt;h3 id=&#34;frequency-band&#34;&gt;Frequency Band&lt;/h3&gt;
&lt;p&gt;Value &lt;code&gt;8&lt;/code&gt; means it&amp;rsquo;s using the &lt;code&gt;2.4 GHz&lt;/code&gt; band, the same crowded-but-universal frequency everything else uses.&lt;/p&gt;
&lt;h3 id=&#34;medium-access-control-capability-flags&#34;&gt;Medium Access Control Capability Flags&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;142&lt;/code&gt; is &lt;code&gt;1000 1110&lt;/code&gt; in binary (LSB &lt;code&gt;0111 0001&lt;/code&gt;):&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Bit&lt;/th&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Value&lt;/th&gt;
					&lt;th&gt;Note&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;Alternate PAN coordinator&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;Can&amp;rsquo;t become a coordinator&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Device type&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Full function, can route&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;Power source&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Mains-powered (not battery)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;Receiver ON when idle&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Always awake and listening&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;Reserved&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;Reserved&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;Reserved&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;Reserved&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;6&lt;/td&gt;
					&lt;td&gt;Security capability&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;Doesn&amp;rsquo;t handle security at this level&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;7&lt;/td&gt;
					&lt;td&gt;Allocate address&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Can help joining new devices&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This looks&amp;hellip; interesting. The security capability bit being zero seems suspicious, but this is my first time digging this deep into a Zigbee descriptor. Maybe Zigbee 3.0 handles security at a different level and this flag is just legacy stuff?&lt;/p&gt;
&lt;h3 id=&#34;manufacturer-code&#34;&gt;Manufacturer Code&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;4742&lt;/code&gt; appears to be Signify Netherlands B.V. (the company behind Philips Hue). This is pretty clever, these bulbs are basically pretending to be Hue bulbs to sneak into a Hue Bridge ecosystem.&lt;/p&gt;
&lt;h3 id=&#34;maximum-buffer-size&#34;&gt;Maximum Buffer Size&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;127&lt;/code&gt; is the most common value and means it can handle the largest standard packet size.&lt;/p&gt;
&lt;h3 id=&#34;maximum-incoming-transfer-size&#34;&gt;Maximum Incoming Transfer Size&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;242&lt;/code&gt; is weird here. To actually transfer chunks this big, the device would need to support packet fragmentation&amp;hellip; but that capability isn&amp;rsquo;t advertised in the APS flags. Something&amp;rsquo;s not adding up.&lt;/p&gt;
&lt;h3 id=&#34;server-mask&#34;&gt;Server Mask&lt;/h3&gt;
&lt;p&gt;All the flags set here are &amp;ldquo;reserved&amp;rdquo;, meaning the device is using them for some non-standard, manufacturer-specific services. Not unusual for Zigbee devices trying to add (or pretending to have) extra features.&lt;/p&gt;
&lt;h3 id=&#34;maximum-outgoing-transfer-size&#34;&gt;Maximum Outgoing Transfer Size&lt;/h3&gt;
&lt;p&gt;Same issue as before, &lt;code&gt;242&lt;/code&gt; suggests it should support large outgoing transfers, but the APS flags don&amp;rsquo;t back that up. Another inconsistency.&lt;/p&gt;
&lt;h3 id=&#34;descriptor-capability-field&#34;&gt;Descriptor Capability Field&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;0&lt;/code&gt; is standard, just confirms there are no extra descriptors beyond the basics.&lt;/p&gt;
&lt;h2 id=&#34;endpoint-1-of-1&#34;&gt;Endpoint 1 of 1&lt;/h2&gt;
&lt;h3 id=&#34;profile-id&#34;&gt;Profile ID&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;0x0104&lt;/code&gt; is Zigbee Light Link (ZLL), the standard profile for smart lights.&lt;/p&gt;
&lt;h3 id=&#34;device-type&#34;&gt;Device Type&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;0x010D&lt;/code&gt; means &amp;ldquo;Extended Color Light.&amp;rdquo; This is exactly what we&amp;rsquo;d expect for a tunable white + RGB bulb, so Home Assistant should recognize it without any issues.&lt;/p&gt;
&lt;h3 id=&#34;input-clusters&#34;&gt;Input Clusters&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;ID&lt;/th&gt;
					&lt;th&gt;Note&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0000&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Basic: Mandatory info like version and manufacturer.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0003&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Identify: Makes the light blink, useful for finding it in a group.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0004&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Groups: Lets you control multiple lights together.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0005&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Scenes: Can save and recall preset colors/brightness.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0006&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;On/Off: The basics.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0008&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Level Control: Dimming.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0300&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Color Control: Handles all the colors and white temperatures.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x1000&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Touchlink Commissioning: Lets you pair by holding it close to a bridge.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0xef00&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Manufacturer Specific: Who knows? Custom feature.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0xfc11&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Manufacturer Specific: Another custom thing.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0xfc57&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Manufacturer Specific: Could be for custom firmware updates.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;output-clusters&#34;&gt;Output Clusters&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;ID&lt;/th&gt;
					&lt;th&gt;Note&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;0x0019&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;OTA Updates: Can receive firmware over-the-air.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;manufacturer&#34;&gt;Manufacturer&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s showing as &lt;code&gt;eWeLink&lt;/code&gt;, but it&amp;rsquo;s super easy to spoof this field when compiling firmware, so this doesn&amp;rsquo;t necessarily mean it&amp;rsquo;s officially from them.&lt;/p&gt;
&lt;h2 id=&#34;model&#34;&gt;Model&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;CK-BL702-AL-01(7009_Z102LG03-1)&lt;/code&gt;, that&amp;rsquo;s a model number alright.&lt;/p&gt;
&lt;h2 id=&#34;class&#34;&gt;Class&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;zigpy.device.Device&lt;/code&gt; means Home Assistant is using a generic driver with no special quirks. It should just work without any fancy custom handling.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Take this with a grain of salt, since it&amp;rsquo;s the first Zigbee device I&amp;rsquo;ve really dug into. But I&amp;rsquo;ll be reviewing a lot more of these soon, I&amp;rsquo;m going all-in on Zigbee and want to really understand how it works under the hood.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Road to Zigbee</title>
            <link>https://bubelov.com/blog/2025/zigbee/</link>
            <pubDate>Sun, 28 Sep 2025 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2025/zigbee/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been using Home Assistant for a couple of years now. I got started, like most people, with some basic Philips lights. They have this cheap line called WiZ (like $15 a light), but you need a special app to set them up. I also tried their fancy Hue line (~$60 per light!) because I wanted to get into motion sensors and have lights that turn on automatically. The big difference is that WiZ uses WiFi, and Hue uses Zigbee.&lt;/p&gt;
&lt;p&gt;At first, I was kinda pissed that WiZ didn&amp;rsquo;t have a motion sensor. But it turns out there&amp;rsquo;s a legit reason, and it&amp;rsquo;s not just the company being greedy. Motion sensors have to be super power-efficient, spending most of their time in a deep sleep to run for a year or more on a battery. WiFi is a total battery hog, so slapping it into a sensor would drain the thing in days. That&amp;rsquo;s the real reason you don&amp;rsquo;t see WiZ sensors.&lt;/p&gt;
&lt;p&gt;Home Assistant totally saved my wallet by letting me mix and match, I could use a Hue Zigbee sensor to trigger my cheap WiZ WiFi lights. But once I got a Zigbee router, I started looking into the protocol and realized it&amp;rsquo;s way better than WiFi for smart home stuff, like in every way. The only thing holding me back from buying more Hue devices was their crazy price.&lt;/p&gt;
&lt;p&gt;Luckily, I found out AliExpress is flooded with no-name Zigbee devices, and I&amp;rsquo;ve been buying them like crazy. The best part is that every new device makes my whole mesh network stronger and more reliable. You really can&amp;rsquo;t beat the prices from China at the moment, it&amp;rsquo;s a total game changer and there are no sane reasons to prefer WiFi.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Philips Hue</title>
            <link>https://bubelov.com/blog/2023/hue/</link>
            <pubDate>Sun, 28 May 2023 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2023/hue/</guid>
            <description>&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Matter_(standard)&#34;&gt;Matter&lt;/a&gt; is an open and privacy-friendly protocol which allows smart home devices to communicate with each other. I&amp;rsquo;ve been reading a lot of good things about it, and I finally decided to buy a few of those Matter-enabled things, namely a &lt;a href=&#34;https://en.wikipedia.org/wiki/Philips_Hue&#34;&gt;Hue&lt;/a&gt; Bridge and a bunch of Hue light bulbs.&lt;/p&gt;
&lt;p&gt;Those toys aren&amp;rsquo;t cheap, so my expectations were high, and I must say, I&amp;rsquo;m really impressed with the quality of those light bulbs. Everything works like a charm, and I really like the flexibility of that system. I set my outdoor lights to turn on automatically fifteen minutes before sunset and then turn off right after midnight.&lt;/p&gt;
&lt;p&gt;My bedroom doesn&amp;rsquo;t really need any timers, but I often change the light temperature and intensity based on what I&amp;rsquo;m doing. I like to start my evening with a bright cold light and then gradually move to a dimmed down warm light as I&amp;rsquo;m preparing for sleep.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Nostr</title>
            <link>https://bubelov.com/blog/2023/nostr/</link>
            <pubDate>Sun, 14 May 2023 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2023/nostr/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been playing with the &lt;a href=&#34;https://nostr.com/&#34;&gt;Nostr&lt;/a&gt; protocol for a few hours, and here are my main takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It has much better fundamentals than Mastodon, and the people behind it are nicer and more competent.&lt;/li&gt;
&lt;li&gt;It can scale, although it won&amp;rsquo;t be trivial. I don&amp;rsquo;t believe it would need to achieve massive scale in order to be useful, anyway.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s trivial to own and backup your data, you&amp;rsquo;re in no way dependent on any server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although the success of Nostr is not certain, I decided to create a simple Nostr to Atom (or RSS) bridge which will allow me to subscribe to Nostr accounts and see their posts in my &lt;a href=&#34;https://github.com/bubelov/news&#34;&gt;News app&lt;/a&gt; feed.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Tailscale</title>
            <link>https://bubelov.com/blog/2022/tailscale/</link>
            <pubDate>Wed, 19 Oct 2022 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2022/tailscale/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been running WireGuard for years and it&amp;rsquo;s been solid. Lately, there&amp;rsquo;s a whole cottage industry of projects trying to slap a shiny GUI on WireGuard to make it &amp;ldquo;easy&amp;rdquo; for non-tech people. Tailscale is the one everyone won&amp;rsquo;t shut up about, so I decided to check it out.&lt;/p&gt;
&lt;p&gt;Verdict: total letdown. It was more annoying to set up than plain WireGuard, and it forces you to use some third-party login. Maybe that makes sense in a corporate hellscape, but certainly not for my self-hosted stuff.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Beej&#39;s Guide to Network Programming (2019)</title>
            <link>https://bubelov.com/blog/2022/beej/</link>
            <pubDate>Tue, 26 Jul 2022 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2022/beej/</guid>
            <description>&lt;p&gt;Although I don&amp;rsquo;t use C professionally, I enjoy reading low-level documentation because it sheds more light on how things work under the hood.
&lt;a href=&#34;https://beej.us/guide/bgnet/&#34;&gt;Beej&amp;rsquo;s Guide to Network Programming&lt;/a&gt; is a great book focused on network sockets and the ways we can interact with them.&lt;/p&gt;
&lt;p&gt;Things like &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;epoll&lt;/code&gt; are the secret sauce that enables higher-level non-blocking IO abstractions such as Kotlin coroutines and async Rust. Anyone curious to see how the sausage gets made will find it worthwhile.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re curious about the author, Brian &amp;ldquo;Beej&amp;rdquo; Jorgensen Hall has been writing software since the early 1990s and first published the guide around 1995. He now teaches computer science at Oregon State University-Cascades in Bend, Oregon.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>CLBOSS</title>
            <link>https://bubelov.com/blog/2022/clboss/</link>
            <pubDate>Sun, 08 May 2022 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2022/clboss/</guid>
            <description>&lt;p&gt;It wouldn&amp;rsquo;t be an exaggeration to say that the success of Bitcoin depends on Lightning Network. This is a level 2 solution which is intended to solve Bitcoin&amp;rsquo;s scalability issues by introducing quite a few clever concepts which every node operator should understand. It&amp;rsquo;s worth noting that all Lightning Network implementations are work in progress, but there are plenty of people who&amp;rsquo;re using them in production without any issues.&lt;/p&gt;
&lt;p&gt;Managing Lightning node is rather hard and time-consuming, and there is a huge demand for automation. &lt;a href=&#34;https://github.com/ZmnSCPxj/clboss&#34;&gt;CLBOSS&lt;/a&gt; is one of the most interesting developments in that space. This plugin can take control of your Core Lightning node and manage it automatically. It can open and close your channels, and it can also make sure that your inbound and outbound liquidity is well-balanced, which is pretty important for routing nodes. It can also watch for network transaction fees, and it prefers to operate when fees are low. Watching how CLBOSS operates can also be a good learning experience if you want to learn the best practices of Lightning node management.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Mastodon</title>
            <link>https://bubelov.com/blog/2022/mastodon/</link>
            <pubDate>Wed, 20 Apr 2022 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2022/mastodon/</guid>
            <description>&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2022/mastodon/og_hu_7288feeb21c73d72.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2022/mastodon/og_hu_e5c35c82f0673ceb.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;The Mastodon logo&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I was a heavy Twitter user once, but those times are long gone. It&amp;rsquo;s not that I don&amp;rsquo;t enjoy Twitter anymore; I just find their business model to be pretty nasty. I had a few Twitter pages in my bookmarks, mostly some people from the Bitcoin community. Apparently, this community decided to migrate to &lt;a href=&#34;https://joinmastodon.org/&#34;&gt;Mastodon&lt;/a&gt;, and it was such a relief for me. Mastodon allows me to subscribe to certain blogs via RSS. Twitter used to be like this, until they decided that sharing content doesn&amp;rsquo;t suit their financial interests.&lt;/p&gt;
&lt;p&gt;I even created my own Mastodon blog, and it turned out to be pretty helpful. Some folks from the Bitcoin community helped me set up a Bitcoin and Lightning node. Mastodon feels like microblogging done right. Highly recommend.&lt;/p&gt;
&lt;p&gt;Mastodon devs finally released an official Android client a few days ago, which could make Mastodon more appealing to a wider audience. Truth be told, Mastodon is much less addictive than Twitter for various reasons, so it&amp;rsquo;s going to be really hard for new users to stick with it. It&amp;rsquo;s not like we have any open alternatives though, so it might be worth the effort.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Miniflux</title>
            <link>https://bubelov.com/blog/2021/miniflux/</link>
            <pubDate>Wed, 29 Sep 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/miniflux/</guid>
            <description>&lt;p&gt;I use webfeeds to fetch news and follow niche blogs. Most websites that are worthy of your attention provide webfeeds, and you can easily add them to your feed reader.&lt;/p&gt;
&lt;p&gt;Feed readers allow you to merge all of your content sources into a single coherent timeline. By the way, that&amp;rsquo;s exactly what &lt;a href=&#34;https://vestifeed.org&#34;&gt;Vesti&lt;/a&gt; does. In many cases, having a simple standalone feed reader app isn&amp;rsquo;t enough because some people use multiple devices and want to keep them in sync.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say I&amp;rsquo;ve already read some news in an Android app and now want to finish reading today&amp;rsquo;s news on my laptop. My Android app should let my laptop know which articles I&amp;rsquo;ve already read so that they aren&amp;rsquo;t shown as unread. These problems can be solved by setting up your own webfeed server and connecting all your apps to this common source of truth.&lt;/p&gt;
&lt;p&gt;Initially, my app supported only one kind of server: Nextcloud News. It works reasonably well, but it&amp;rsquo;s pretty slow and hard to set up. I recently learned about a server called &lt;a href=&#34;https://miniflux.app/&#34;&gt;Miniflux&lt;/a&gt;, and it turned out to be the best feed server I&amp;rsquo;ve ever seen. It&amp;rsquo;s ridiculously simple to set up and blazing fast, so I decided to support Miniflux in the next Vesti release.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>USB Everywhere</title>
            <link>https://bubelov.com/blog/2021/usb-everywhere/</link>
            <pubDate>Wed, 15 Sep 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/usb-everywhere/</guid>
            <description>&lt;p&gt;Two good USB-related events this month:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EU plans to force all device manufacturers to adopt USB-C.&lt;/li&gt;
&lt;li&gt;USB accessories will soon have a special markings, making it easy to figure out their capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s sad that Apple provoked more regulations, other market participants seem to converge on USB-C voluntarily. Anyway, this regulation is good for iPhone users and for the environment. I think it&amp;rsquo;s mostly a failure of antitrust regulations though.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Tor Switches to Rust</title>
            <link>https://bubelov.com/blog/2021/tor-rust/</link>
            <pubDate>Sat, 24 Jul 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/tor-rust/</guid>
            <description>&lt;p&gt;Writing software is hard, mostly because the expectations are rather high. We want our software to be cheap, safe, fast, reliable, easy to use, and that&amp;rsquo;s just a few things to start with. There is also a reason why we have so many tools and languages: different software projects have different sets of priorities.&lt;/p&gt;
&lt;p&gt;What do we want from a project like &lt;a href=&#34;https://www.torproject.org/&#34;&gt;Tor&lt;/a&gt;? Well, we want everything, but, if we have to prioritize, safety comes on the top of the list. That&amp;rsquo;s why I&amp;rsquo;m very excited to hear that Tor developers have &lt;a href=&#34;https://blog.torproject.org/announcing-arti&#34;&gt;decided&lt;/a&gt; to embrace Rust. Here is what they&amp;rsquo;re saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For us, these problems mean that programming in C is a slow and painstaking process. Everything we write takes more code than we&amp;rsquo;d like it to, and we need to double-check even the safest-looking code to make sure it doesn&amp;rsquo;t fall prey to any of C&amp;rsquo;s list of enormous gotchas. This slows us down seriously, and increases the cost of adding new features.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust seems like the clearest way out of our bind. It&amp;rsquo;s a high-level language, and significantly more expressive than C. What&amp;rsquo;s more, it&amp;rsquo;s got some really innovative features that let the language enforce certain safety properties at compile-time. To a first approximation, if the code compiles, and it isn&amp;rsquo;t explicitly marked as &amp;ldquo;unsafe&amp;rdquo;, then large categories of bugs are supposed to be impossible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;That&amp;rsquo;s a huge win for us in programming and debugging time, and a huge win for users in security and reliability.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        
        <item>
            <title>Setting Up SSH Passwordless Auth</title>
            <link>https://bubelov.com/blog/2021/ssh-passwordless/</link>
            <pubDate>Wed, 23 Jun 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/ssh-passwordless/</guid>
            <description>&lt;p&gt;There are many ways to access remote servers, but the most popular is &lt;a href=&#34;https://en.wikipedia.org/wiki/Secure_Shell_Protocol&#34;&gt;Secure Shell Protocol&lt;/a&gt; (SSH). All popular operating systems ship with an SSH client and server packages installed by default, which means you can connect to other computers as well as to allow them to use your machine. That&amp;rsquo;s cool, but also a bit concerning: how can we make sure only the right people can access our computers?&lt;/p&gt;
&lt;p&gt;There are many ways to authorize via SSH, but the most popular are password auth and key-based auth. Among those two methods, key-based auth is preferable because it&amp;rsquo;s much harder to guess an average cryptographic key than the average password. You can use SSH to generate so-called public-private key pair. After that, you can copy your public key to a machine you want to access remotely and place it in &lt;code&gt;authorized_keys&lt;/code&gt; directory. After that, you can go ahead and connect to that computer without typing any passwords. This method is both convenient and secure.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say we generated a key pair already, how do we copy our public key to a remote host? Looks like a chicken and egg problem. Many VPS providers solve this problem by asking for your public key before creating your first server, so they can add it to &lt;code&gt;authorized_keys&lt;/code&gt; every time they bring up a fresh server for you. Another way to set up key-based auth is to start with password auth and then use a program called &lt;code&gt;ssh-copy-id&lt;/code&gt;. It will attempt normal password auth and, once you type your password, it will add your public key to &lt;code&gt;authorized_keys&lt;/code&gt; directory on the remote host. In other words, this program &amp;ldquo;pushes&amp;rdquo; your public key to a remote server. The downside? You have to enable less secure password auth first and then manually turn it off.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been happily using &lt;code&gt;ssh-copy-id&lt;/code&gt; for years, but this mouth, I&amp;rsquo;ve found out that it&amp;rsquo;s also possible to &amp;ldquo;pull&amp;rdquo; my public key without setting up password auth. It&amp;rsquo;s especially useful when I have physical access to a new machine, and I want to be able to connect to it remotely from my main computer at a latter stage. How is it possible to pull a public key from a machine which might be out of reach? Even if it&amp;rsquo;s reachable, it won&amp;rsquo;t give any files to an unrecognized client. We have a chicken and egg problem again. Well, pretty much everyone uses GitHub, and it will happily give you public keys of any user. Public keys aren&amp;rsquo;t secret, so there is no reason to hide them anyway. The tool that can pull public keys of any GitHub user is called &lt;code&gt;ssh-import-id&lt;/code&gt; and it&amp;rsquo;s installed by default on most Linux distributions.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wi-Fi 6 Router</title>
            <link>https://bubelov.com/blog/2021/wifi-6-router/</link>
            <pubDate>Sat, 17 Apr 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/wifi-6-router/</guid>
            <description>&lt;p&gt;First, let me say that Wi-Fi 6 is not a revolutionary change in wireless communications. Yes, it&amp;rsquo;s a bit faster, and it has certain features aimed to make Wi-Fi more efficient in crowded places, but overall, I didn&amp;rsquo;t notice any difference in my home setup. I just saw a banner on my Internet provider&amp;rsquo;s website, and I decided to ask my provider about the possibility of upgrading the router. It uses GPON, so I can&amp;rsquo;t really go shopping and pick any router I like, unfortunately. It turned out, they offer free router upgrades, so I decided to use this opportunity. The router hardware is faster, which allows it to keep latency low under load, and their new firmware finally got advanced enough to allow custom MAC to IP mappings. I really missed that feature. Those improvements have nothing to do with Wi-Fi 6, by the way.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>State of the Lightning Network</title>
            <link>https://bubelov.com/blog/2021/state-of-lightning/</link>
            <pubDate>Wed, 24 Feb 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/state-of-lightning/</guid>
            <description>&lt;p&gt;I continued my experiments with Lightning Network. My focus was on the things that can go wrong if you decide to operate a Lightning node. It turned out, a lot of things can go wrong ranging from the typical ops problems such as hardware failures to the exotic and counterintuitive ones, such as Lightning backups.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with the counterintuitive issues, as they&amp;rsquo;re more interesting. Every good sysadmin knows that having regular backups is essential to make sure your data is safe. Having a backup is always good, it protects you from losing your precious data. When it comes to managing Lightning nodes, having a full backup can be an extremely dangerous thing because it can lead to the loss of your funds. The thing is: Lightning Network prevents cheating by punishing people for presenting an outdated states of their channels.&lt;/p&gt;
&lt;p&gt;The reason is pretty simple, let&amp;rsquo;s say you opened a channel with a local bar, and it started with $100 on your side and $0 on the side of the bar. At some time in the future, all the money ends up on the side of the bar, since you paid with Lightning Network. What makes Lightning Network so fast and cheap compared with Bitcoin is the fact that you can move money from one side of your channel to another without triggering a costly and slow Bitcoin transaction, but as some point, you&amp;rsquo;ll want to close the channel and both sides will be able to reclaim their bitcoins. Both sides know the latest state of the channel and if any side tries to cheat and broadcast a previous state ($100 on your side, for example), the other side can prove that it has a newer state and get all the money as a reward for detecting cheating. Well, the problem is: backups tend to have older states, so they can be seen as cheating, that&amp;rsquo;s why it isn&amp;rsquo;t a good idea to use full backups.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s crazy, right? How can we back up a Lightning node? There is a mechanism called &lt;a href=&#34;https://github.com/lightningnetwork/lnd/blob/master/docs/recovery.md&#34;&gt;Static Channel Backup&lt;/a&gt;. It&amp;rsquo;s not ideal, but it should work. The problem with this kind of backup is that it won&amp;rsquo;t recover your channels in case of a node failure. It can only recover your bitcoins by force-closing all of your channels.&lt;/p&gt;
&lt;p&gt;There are currently no reliable ways to back up and restore Lightning channels. The best thing an operator can do is to minimize the probability of a node failure. What can fail if you&amp;rsquo;re running Raspiblitz on a Raspberry Pi 4?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The board itself. Just buy more boards and you&amp;rsquo;ll be fine.&lt;/li&gt;
&lt;li&gt;An SD card. Again, redundancy is you friend. Just keep a spare SD card and you&amp;rsquo;ll be able to recover your node without using backups.&lt;/li&gt;
&lt;li&gt;An SSD/HDD. Failure of a main storage device would be a problem. Luckily for us, SSD/HDD failure rates are pretty low, and it&amp;rsquo;s unlikely to happen. If you&amp;rsquo;re paranoid, set up a RAID array with a comfortable level of redundancy. I think it&amp;rsquo;s an overkill unless your node is handling a lot of money.&lt;/li&gt;
&lt;li&gt;Electricity shortage. Unexpected shutdowns can corrupt your data, and you have to avoid such situations. Buying a good UPS should solve that problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, good old redundancy can solve most of your problems if you want to operate a highly available Lightning node. Backups are tricky because using wrong backups can lead to the loss of money and using proper backups leads to force-closing all of your channels. Losing your channels is unfortunate, but it&amp;rsquo;s a &amp;ldquo;worst case&amp;rdquo; that shouldn&amp;rsquo;t really happen. Even if you&amp;rsquo;re unlucky, the only thing you would lose is blockchain transaction fees.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Webfeeds</title>
            <link>https://bubelov.com/blog/2020/web-feeds/</link>
            <pubDate>Mon, 21 Dec 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/web-feeds/</guid>
            <description>&lt;p&gt;I stopped using social networks a couple of years ago, and I never looked back. Social networks are full of bullshit and self-promotion and this kind of content doesn&amp;rsquo;t really resonate with me. I get it, some people want to know what&amp;rsquo;s up with their closest friends, but the thing is, most of the people we get constant updates from via the social media are not our close friends. Using a social network feels like being a guinea big in some kind of social experiment in human deception.&lt;/p&gt;
&lt;p&gt;I get most of the news from RSS and Atom feeds. It&amp;rsquo;s so much better this way. The closest thing to this experience is Reddit. I was addicted to Reddit for quite a while, and it felt much better than other mainstream social media, probably because it was built around certain topics and not people, so it was much easier to find something interesting.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>The World Needs Another Feed Reader</title>
            <link>https://bubelov.com/blog/2020/another-feed-reader/</link>
            <pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/another-feed-reader/</guid>
            <description>&lt;p&gt;Okay, maybe it&amp;rsquo;s just me. Anyway, here is the source code:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/bubelov/news&#34;&gt;https://github.com/bubelov/news&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been working on this thing for the last few weeks, and it&amp;rsquo;s still a bit rough around the edges, but I already use it, and it serves me well. I tried to post it to Google Play, but it seems like Google is trying to force the developers to use Chrome instead of Firefox, again:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2020/another-feed-reader/google-play-console_hu_ee2172fec5e98529.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2020/another-feed-reader/google-play-console_hu_a769546cf5c25942.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;It only works with Nextcloud, but I&amp;rsquo;m planning to add a standalone mode in the coming weeks.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>WireGuard</title>
            <link>https://bubelov.com/blog/2020/wireguard/</link>
            <pubDate>Sat, 30 May 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/wireguard/</guid>
            <description>&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2020/wireguard/og_hu_9e224c19e99dc187.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2020/wireguard/og_hu_e0e15b4417f477c0.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I have a Nextcloud server in my house, and it works great inside my local network, but it also needs to be reachable from the Internet and that&amp;rsquo;s where it gets a bit tricky. My server has a local IP, but it doesn&amp;rsquo;t have a globally reachable IP, and there are no easy ways to get one from a regular residential ISP.&lt;/p&gt;
&lt;p&gt;The most convenient way to reach a website is by its domain name. Any browser can execute a DNS query to figure out the actual IP addresses behind a particular domain name you&amp;rsquo;re trying to access, and once that address is found, your browser of choice can finally initiate a connection.&lt;/p&gt;
&lt;p&gt;So, my Nextcloud server needs the following things to be globally reachable:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A domain.&lt;/li&gt;
&lt;li&gt;A unique IP address to point that domain to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I already had a domain and the only thing missing was a unique IP address to put inside an &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_DNS_record_types&#34;&gt;A record&lt;/a&gt;. It turned out that Digital Ocean has a data center close enough (ping &amp;lt; 30 ms) to my house, and I decided to rent a cheap virtual machine there and use its globally reachable IP address for my local Nextcloud server.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s fair to stop there and ask yourself &amp;ldquo;why didn&amp;rsquo;t this guy just host his stupid Nextcloud on that droplet directly? What&amp;rsquo;s the point of hosting stuff from home?&amp;rdquo;. Those are good questions and the answer is: privacy and cost. I don&amp;rsquo;t want to hold my private data anywhere except in my house, and I also don&amp;rsquo;t want to pay a lot of money for storage space that I already have and can use for free. Even buying a new HDD or an SSD is much, much cheaper than renting the equivalent space in the cloud.&lt;/p&gt;
&lt;p&gt;So, my domain&amp;rsquo;s A record can point all the traffic to that DO droplet, which has a unique and globally reachable IP address, so the only extra thing I needed to do was to connect my home server with that VM somehow. I had heard that setting up OpenVPN is not particularly easy, and I wanted to find an easier solution. A few web searches later, I ended up reading about a tool called &lt;code&gt;autossh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.wirelessmoves.com/2019/06/how-to-run-a-server-at-home-without-an-ipv4-address.html&#34;&gt;This excellent post&lt;/a&gt; helped me get it up and running in no time but, unfortunately, &lt;code&gt;autossh&lt;/code&gt; is kind of cryptic and sometimes it just stops working without logging any reason why. That&amp;rsquo;s why I had to get rid of &lt;code&gt;autossh&lt;/code&gt; and find a way to set up a proper VPN.&lt;/p&gt;
&lt;p&gt;It turned out that setting up a VPN can be pretty easy, thanks to &lt;a href=&#34;https://www.wireguard.com&#34;&gt;WireGuard&lt;/a&gt;. It&amp;rsquo;s also the &lt;a href=&#34;https://www.wireguard.com/performance&#34;&gt;fastest&lt;/a&gt; out there. I highly recommend using WireGuard if you need a fast and reliable connection between your home computer and some server on the Internet.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>RSS Tricks</title>
            <link>https://bubelov.com/blog/2020/rss-tricks/</link>
            <pubDate>Thu, 16 Jan 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/rss-tricks/</guid>
            <description>&lt;p&gt;RSS is a great way to subscribe to various blogs, but it can be used for a lot of other things. For instance, you can get notified of new releases of any GitHub project right from your RSS feed. Here is an example:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/rust-lang/rust/releases.atom&#34;&gt;https://github.com/rust-lang/rust/releases.atom&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also possible to add your favorite YouTube channels to your RSS feed. For example, here is a link to a &lt;a href=&#34;https://www.youtube.com/feeds/videos.xml?channel_id=UCZEPItn2Nb62Zso5eohHAAA&#34;&gt;BBC Documentary feed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, YouTube feed links have the following format:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;https://www.youtube.com/feeds/videos.xml?channel_id=&amp;lt;id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;BBC Documentary&amp;rsquo;s &lt;code&gt;channel_id&lt;/code&gt; is &lt;code&gt;UCZEPItn2Nb62Zso5eohHAAA&lt;/code&gt; and you can get the ID&amp;rsquo;s of your favorite channels by inspecting your address bar when they are open.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Thunderbolt 4 and USB 4</title>
            <link>https://bubelov.com/blog/2020/thunderbolt-4-usb-4/</link>
            <pubDate>Mon, 13 Jan 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/thunderbolt-4-usb-4/</guid>
            <description>&lt;p&gt;Thunderbolt 3 is an interface that is available on pretty much every high-end laptop nowadays. It&amp;rsquo;s almost too good to be true. Thunderbolt-enabled hardware have a set of unified USB ports that can be connected to up to four PCIe 3.0 lanes. One such lane gives us up to 8 GT/s (985 MB/s), so it should give us up to 32 GT/s, although Intel claims that it&amp;rsquo;s capable of 40 GT/s. I&amp;rsquo;m not sure where those extra 8 GT/s come from, but many people claim that their Thunderbolt 3 devices are only capable of ~22 GT/s. Anyway, it&amp;rsquo;s crazy fast!&lt;/p&gt;
&lt;p&gt;Fast transfer speed is not the only benefit of Thunderbolt 3, it also allows us to charge our devices or send video output to external monitors. It&amp;rsquo;s also possible to use an external GPU and even Ethernet over Thunderbolt. Think of a small GPU enclosure that you can connect to your laptop with a single USB cable and aside from being able to do many GPU-intensive tasks, it would also keep your laptop charged and route your traffic via a wired interface which may improve your network throughput and latency. It&amp;rsquo;s a truly amazing little port.&lt;/p&gt;
&lt;p&gt;So, on CES 2020 keynote, Intel announced a new generation of Thunderbolt: Thunderbolt 4, which left many people excited and confused at the same time. Intel promised some speed improvements, so it&amp;rsquo;s supposed to be 4 times faster than&amp;hellip; USB 3.2. 2x1. Well, that was unexpected. Why do they compare Thunderbolt 4 to USB when they have Thunderbolt 3 as a more clear point of reference? They announced that Thunderbolt 4 is 4 times faster than USB 3.2. 2x1, which means 40 GT/s, same speed as Thunderbolt 3. That&amp;rsquo;s very strange, maybe they&amp;rsquo;ll clarify things later.&lt;/p&gt;
&lt;p&gt;Aside from Thunderbolt standards, now we also have USB4 out in the wild. It&amp;rsquo;s practically the same thing as Thunderbolt 3, nothing new and exciting, but at least it&amp;rsquo;s not semi-proprietary which is nice. It looks like we&amp;rsquo;re going to stick with 40 GT/s for a while.&lt;/p&gt;
&lt;p&gt;Actually, I expected that Intel would use the full potential of PCIe 4.0 which doubles the bandwidth to 16 GT/s (1970 MB/s) per every lane. A man can dream.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wi-Fi vs Wired Networking on Raspberry Pi 4</title>
            <link>https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/</link>
            <pubDate>Mon, 06 Jan 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/</guid>
            <description>&lt;p&gt;I ran a few tests to find out how to boost network transfer speed on the Raspberry Pi 4, and whether it&amp;rsquo;s worth the hassle.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/thumb_hu_ae31b57f54588bed.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/thumb_hu_bb70513815eda101.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#tldr&#34;&gt;TL;DR&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#preface&#34;&gt;Preface&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#test-structure&#34;&gt;Test Structure&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#generating-test-data&#34;&gt;Generating Test Data&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#testing-data-throughput-over-wi-fi-and-ethernet&#34;&gt;Testing Data Throughput Over Wi-Fi and Ethernet&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#results&#34;&gt;Results&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#testing-raspberry-pi-4-throughput-with-iperf&#34;&gt;Testing Raspberry Pi 4 Throughput With iPerf&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Prefer wired connections when it&amp;rsquo;s not too inconvenient. For maximum data throughput, you should also use an SSD because regular SD cards won&amp;rsquo;t let you fully utilize the potential of your wired connection.&lt;/p&gt;
&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;
&lt;p&gt;The Raspberry Pi 4 is a capable SBC that comes with two built-in network interfaces: &lt;a href=&#34;https://en.wikipedia.org/wiki/Gigabit_Ethernet&#34;&gt;Gigabit Ethernet&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802.11ac-2013&#34;&gt;IEEE 802.11ac Wi-Fi&lt;/a&gt;. Having options is good, but it&amp;rsquo;s also a common source of confusion. Which interface should we use and why?&lt;/p&gt;
&lt;p&gt;In this article, I compare wired and Wi-Fi interfaces in terms of their maximum data throughput. If you&amp;rsquo;re new to networking, you might also benefit from reading about network latency and its role in the performance of networked software. In short, wired connections usually have an order of magnitude better latency than wireless ones, and that might be more important than the amount of megabytes you can push per second. That said, let&amp;rsquo;s do some tests!&lt;/p&gt;
&lt;p&gt;First, it&amp;rsquo;s good to keep in mind that we can&amp;rsquo;t trust the benchmarks completely. Real-world performance can depend on many factors, and it&amp;rsquo;s always a good idea to reproduce the same tests with your own hardware and in your own environment.&lt;/p&gt;
&lt;h2 id=&#34;test-structure&#34;&gt;Test Structure&lt;/h2&gt;
&lt;p&gt;Here is what my test does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate 1 GB of random data on my laptop&lt;/li&gt;
&lt;li&gt;Send this data to my Raspberry Pi and measure the average speed&lt;/li&gt;
&lt;li&gt;Fetch this data from my Raspberry Pi and measure the average speed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I repeated this test with four different configurations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A Raspberry Pi that uses Wi-Fi and stores data on an SD card&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Wi-Fi and stores data on an SSD&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Ethernet and stores data on an SD card&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Ethernet and stores data on an SSD&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s it. Now, it&amp;rsquo;s time to generate that random data.&lt;/p&gt;
&lt;h2 id=&#34;generating-test-data&#34;&gt;Generating Test Data&lt;/h2&gt;
&lt;p&gt;We can use &lt;code&gt;dd&lt;/code&gt; to generate a new file and &lt;code&gt;/dev/urandom&lt;/code&gt; is a great data source:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dd if=/dev/urandom of=big.file bs=64M count=16 iflag=fullblock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s clarify these arguments and their purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;if&lt;/code&gt; - input file. In our case, we attach our input to the stream of random data available on any Linux distribution.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;of&lt;/code&gt; - output file. It&amp;rsquo;s the name of the file we want to create. Feel free to use any name you want.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bs&lt;/code&gt; - in our case, it means that we want to generate our random file piece by piece and there should be &lt;code&gt;count&lt;/code&gt; pieces in it. It also means that we can tweak both arguments; the only important thing is that &lt;code&gt;bs&lt;/code&gt; * &lt;code&gt;count&lt;/code&gt; should be close to our target size (1 GB).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; - as mentioned above, it&amp;rsquo;s just a multiplier for &lt;code&gt;bs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;testing-data-throughput-over-wi-fi-and-ethernet&#34;&gt;Testing Data Throughput Over Wi-Fi and Ethernet&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s send some data to the Raspberry Pi (&lt;code&gt;Laptop --&amp;gt; Pi&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rsync --progress big.file pi@cloud.local:~/big.file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;big.file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  1,073,741,824 100%   32.10MB/s    0:00:31 (xfr#1, to-chk=0/1)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I used &lt;code&gt;rsync&lt;/code&gt; because it&amp;rsquo;s easy to use, and it reflects my real workloads (syncing a lot of files, doing backups and so on).&lt;/p&gt;
&lt;p&gt;Now we can download that big file from the Raspberry Pi and measure the average transfer speed (&lt;code&gt;Laptop &amp;lt;-- Pi&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rsync --progress pi@cloud.local:~/big.file big.file.back
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;big.file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  1,073,741,824 100%   42.69MB/s    0:00:23 (xfr#1, to-chk=0/1)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it. I repeated this test for each of the tested setups, and here are the results:&lt;/p&gt;
&lt;h2 id=&#34;results&#34;&gt;Results&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;From&lt;/th&gt;
					&lt;th&gt;To&lt;/th&gt;
					&lt;th&gt;Interface&lt;/th&gt;
					&lt;th&gt;Storage&lt;/th&gt;
					&lt;th&gt;Speed (Mbit/s)&lt;/th&gt;
					&lt;th&gt;Speed (MB/s)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;58.24&lt;/td&gt;
					&lt;td&gt;7.28&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;55.84&lt;/td&gt;
					&lt;td&gt;6.98&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;159.60&lt;/td&gt;
					&lt;td&gt;19.95&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;340.56&lt;/td&gt;
					&lt;td&gt;42.57&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;80.72&lt;/td&gt;
					&lt;td&gt;10.09&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;82.00&lt;/td&gt;
					&lt;td&gt;10.25&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;339.20&lt;/td&gt;
					&lt;td&gt;42.40&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;341.52&lt;/td&gt;
					&lt;td&gt;42.69&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Interesting results, but let&amp;rsquo;s try an alternative approach to measuring network throughput before jumping to any conclusions.&lt;/p&gt;
&lt;h2 id=&#34;testing-raspberry-pi-4-throughput-with-iperf&#34;&gt;Testing Raspberry Pi 4 Throughput With iPerf&lt;/h2&gt;
&lt;p&gt;We can easily measure &amp;ldquo;raw&amp;rdquo; network performance by moving as much data as possible between two computers for a certain period of time. One of those computers has to play the role of a client by generating a lot of gibberish and sending it to the second machine, which can simply discard all of that traffic upon arrival.&lt;/p&gt;
&lt;p&gt;There are many ways to perform such a test, but &lt;code&gt;iperf&lt;/code&gt; is something of an industry standard, and it&amp;rsquo;s very easy to use, which makes it a good choice for our quick test.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s make Raspberry Pi 4 a server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh pi@pi.local
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install iperf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;iperf --server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Server listening on TCP port 5001
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TCP window size: 85.3 KByte (default)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can use &lt;code&gt;iperf&lt;/code&gt; from another computer and instruct it to connect to the Raspberry Pi in order to measure the network throughput between them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install iperf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;iperf --client pi.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client connecting to cloud.local, TCP port 5001
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TCP window size: 85.0 KByte (default)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[ ID] Interval       Transfer     Bandwidth
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[  3]  0.0-10.0 sec  1.10 GBytes   942 Mbits/sec
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here are my results for wired and Wi-Fi connections:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Interface&lt;/th&gt;
					&lt;th&gt;Speed (Mbit/s)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;942&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Wi-Fi (IEEE 802.11ac)&lt;/td&gt;
					&lt;td&gt;86&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both tests point to the same conclusion.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Although using Wi-Fi is more convenient because it gives you more flexibility, don&amp;rsquo;t expect your network transfer speed to be anywhere above 86 Mbit/s if you connect your Raspberry Pi wirelessly. 86 Mbit/s is actually not that bad if you use an SD card because many modern SD cards can&amp;rsquo;t go beyond ~80 Mbit/s when they write data, although they can read a bit faster. Not being able to take advantage of that extra read speed is the main drawback of using Wi-Fi on a Raspberry Pi 4.&lt;/p&gt;
&lt;p&gt;Things get a bit different if you prefer to store your data on an SSD. Modern solid-state drives can move gigabytes in seconds, but your Wi-Fi connection wouldn&amp;rsquo;t let you take advantage of that extra throughput. Switching to a wired connection boosts transfer speed up to about 30-40 MB/s when using &lt;code&gt;rsync&lt;/code&gt;, which is better, but still a far cry from the theoretical limit of 125 MB/s (that&amp;rsquo;s the max speed of a Gigabit Ethernet adapter that is used in Raspberry Pi 4). It might be due to encryption overhead, which puts some pressure on the CPU and makes it a bottleneck. That&amp;rsquo;s precisely why benchmarking is hard: there are many components that might affect the results.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>RSS is Live and Kicking</title>
            <link>https://bubelov.com/blog/2019/rss-is-live-and-kicking/</link>
            <pubDate>Mon, 21 Oct 2019 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2019/rss-is-live-and-kicking/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been experimenting with using Nextcloud as my RSS aggregator for the last couple of weeks. It works, but I wouldn&amp;rsquo;t call it the best option.&lt;/p&gt;
&lt;p&gt;The main reason I&amp;rsquo;m hesitant is the lack of visible development activity in the backend code and the official Android app. When a core feature feels stagnant, it&amp;rsquo;s hard to trust its long-term future.&lt;/p&gt;
&lt;p&gt;There is a notable upside, though: the built-in RSS server is compatible with third-party clients like the popular &lt;a href=&#34;https://jangernert.github.io/FeedReader/&#34;&gt;FeedReeder&lt;/a&gt; for Linux. This interoperability is a solid feature that keeps it usable even if the native apps lag behind.&lt;/p&gt;
&lt;p&gt;My trial is ongoing. If Nextcloud doesn&amp;rsquo;t feel solid by the end of it, my fallback plan is to set up a dedicated &lt;a href=&#34;https://tt-rss.org/&#34;&gt;Tiny Tiny RSS&lt;/a&gt; server, which has a reputation for being robust and actively maintained.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>