<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/index.xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>./techtipsy</title><link>https://ounapuu.ee/categories/self-hosting/</link><description>Recent content on ./techtipsy, a blog written by Herman Õunapuu.</description><generator>Hugo -- gohugo.io</generator><language>en-GB</language><managingEditor>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</managingEditor><webMaster>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</webMaster><lastBuildDate>Wed, 06 May 2026 06:00:00 +0300</lastBuildDate><atom:link href="https://ounapuu.ee/categories/self-hosting/index.xml" rel="self" type="application/rss+xml"/><item><title>How I self-host this blog at home with a dynamic IPv4 address, IPv6 prefix, and a dash of Wireguard</title><link>https://ounapuu.ee/posts/2026/05/06/self-host-at-home/</link><pubDate>Wed, 06 May 2026 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/05/06/self-host-at-home/</guid><description>I think I've finally figured it out. For now.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/05/06/self-host-at-home/media/cover_hu_a0e9c758122adadf.jpg" width="1200" height="630" alt="How I self-host this blog at home with a dynamic IPv4 address, IPv6 prefix, and a dash of Wireguard" /><p>Networking has long been my Achilles heel. I know the very basics, but the more complex areas of networking have been a
bit puzzling to me. By the time I figured out how IPv4 works, I found IPv6 and that my ISP supports it.</p>
<p>Back to square one.</p>
<p>That didn&rsquo;t stop me from learning some bits, and after 8+ years of self-hosting as a hobby, I&rsquo;ve settled on a setup that
works for me and overcomes common residential internet connection nuances, such as dynamic IPv4 addresses and changing
IPv6 prefixes. I&rsquo;m sharing these tips and tricks with the goal of helping out other hobbyists out there that happen to
share a similar stack.</p>
<h2 id="background">
  <a class="heading-anchor" href="#background">Background<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My ISP is polite enough to provide a public IPv4 address, and allowing incoming traffic is a toggle in their online
self-service. Not perfect, but at least you can do it. However, they charge about 6 EUR a month for the static IP
address service, which I am not willing to pay out of principle.</p>
<p>They also support IPv6, which is great, and they provide you a whole <code>/56</code> slice of it to play with using IPv6 prefix
delegation. Unfortunately they have configured the lease time for the prefix to be incredibly short: 26 <strong>minutes</strong>!</p>
<p>A router reboot or short power outage usually results in the IPv4 address and IPv6 prefix changing, which is really
annoying as my services become unavailable for a short time.</p>
<h2 id="dynamic-dns">
  <a class="heading-anchor" href="#dynamic-dns">Dynamic DNS<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>A common way to overcome the dynamic IP address limitation is to sign up with a provider to set up a DNS record that
changes whenever your home IP address changes. My domain registrar does not have this as a feature, and I&rsquo;m not
interested in using a different provider, so I went in a different direction and built a home-grown script that does the
same thing.</p>
<p>Initially, this script relied on a public service that tells you what your IP address is, and based on that I could
check if things have changed and I need to update my DNS record. This approach has one glaring catastrophic failure mode
though: that provider could lie to you one day and now you&rsquo;ve pointed your DNS records at the attackers&rsquo; servers. :)</p>
<p>I ignored that failure mode for a while, but once I learned about the effectiveness of LLM-based tooling, I decided to
give it a go and to build a better solution that takes into account my setup and requirements, while at the same time
saving me from the frustration of troubleshooting and debugging this in a late evening. I&rsquo;m still very limited on
available free time, so optimizing for that is a priority for me.</p>
<p>My main networking gear runs OpenWRT, and it supports running shell scripts periodically in a crontab. The router has
two WAN interfaces, one for IPv4 and one for IPv6. It already knows what IP address and prefix have been assigned to it,
so I don&rsquo;t have to rely on an external service provider for finding this out.</p>
<p>Handling IPv4 addresses is simple: check the IPv4 address of the WAN interface. Query your existing DNS records, diff
it, and if it has changed, push an update in a separate API call. Super simple!</p>
<p>With IPv6, the approach is slightly different. Instead of the WAN interface, I have to get the IPv6 address of the
target machine, and make sure that it&rsquo;s routable over the public internet. When you&rsquo;ve checked your network settings in
an IPv6 network, you may have noticed a lot of different IP addresses there, with lots of letters thrown into the mix.</p>
<p>Here&rsquo;s an example from the machine that is serving you this blog (likely out of date though!):</p>
<pre tabindex="0"><code>    inet6 fdb3:6dad:6dce::f41/128 scope global dynamic noprefixroute 
    inet6 fdb3:6dad:6dce:0:2e0:4cff:fe0c:9ddb/64 scope global noprefixroute 
    inet6 2001:7d0:856c:4000::f41/128 scope global dynamic noprefixroute 
    inet6 2001:7d0:856c:4000:2e0:4cff:fe0c:9ddb/64 scope global dynamic noprefixroute 
    inet6 fe80::2e0:4cff:fe0c:9ddb/64 scope link noprefixroute 
</code></pre><p>The two relevant ones are the ones that start with <code>2001:</code>, others are link-local or accessible over the local network
only. The shorter one consists of the IPv6 prefix part, and then the unique bit at the end is a predictable suffix that
the host gets. The other one also works, but is as far as I understand randomly generated and more difficult to predict
when we get around to next sections.</p>
<p>I know that there is probably a better way to do this, but I wanted to keep things simple enough so that I can
troubleshoot them if needed. It may be possible to trigger this updater script on events that WAN and WAN6 interfaces
send, but I have not validated this theory.</p>
<p>There are many different ways to find the IPv6 address of a particular host, so the script I have just tries multiple
approaches to find the one that we&rsquo;re looking for.</p>
<p><a href="/posts/2026/05/06/self-host-at-home/media/ddns.sh">Here&rsquo;s the script</a> in case you&rsquo;re interested in setting up something similar. It reads credentials from
an .env file and is built around <a href="https://api.zone.eu/">the Zone API</a>. On OpenWRT, the only dependency that you need to
install is <code>curl</code>, which to my surprise was not part of the default packages list, probably to save on space.</p>
<p>One lesson I learned from a previous iteration of the script: if you trigger DNS record updates every minute, then Zone
will actually reach out to you via e-mail telling you to cut that shit out, politely. It was just one missing <code>if</code>
statement, and yet it caused some frustration to engineers far away. Sorry!</p>
<h2 id="predictable-ip-addresses">
  <a class="heading-anchor" href="#predictable-ip-addresses">Predictable IP addresses<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s a good idea to set up static IP addresses for your hosts, both for IPv4 addresses and IPv6 prefix delegation via
DUID-s.</p>
<p>The OpenWRT GUI LuCI makes it quite simple, just set the addresses as static on the landing page for the hosts
that you are interested in forwarding traffic to, and you&rsquo;re done!</p>
<p>My recommendation here is to also set a predictable IPv6 suffix, otherwise all your IPv6 traffic rules may break once
again due to this nuance.</p>
<p>I like to make that host number the same for both IPv4 and IPv6, quick example:</p>
<ul>
<li><code>192.168.1.2</code></li>
<li><code>2001:7d0:854f:8e00::2</code></li>
</ul>
<p>Here&rsquo;s a configuration snippet example from <code>/etc/config/dhcp</code>, look for the <code>hostid</code> option:</p>
<pre tabindex="0"><code>config host
        option name &#39;mycoolserver&#39;
        option ip &#39;192.168.1.69&#39;
        list mac &#39;12:34:56:78:90:AB&#39;
        option duid &#39;yourduidgoeshere&#39;
        option hostid &#39;69&#39;
</code></pre><p>Apply with <code>service dnsmasq restart</code>.</p>
<p>In LuCI, as of OpenWRT 25.12, look for &ldquo;IPv6 token&rdquo;.</p>









<figure class="center">
  <a href="/posts/2026/05/06/self-host-at-home/media/ipv6token.png">
    <img src="/posts/2026/05/06/self-host-at-home/media/ipv6token_hu_556676a81dfcb972.webp"
     width="1000"
     height="103"
     loading="lazy"
     decoding="async"
     alt="Set an IPv6 token for a predictable IPv6 suffix.">

  </a>
  <figcaption class="center">Set an IPv6 token for a predictable IPv6 suffix.</figcaption>
</figure>

<p>Note that due to a bug, it doesn&rsquo;t seem to be possible to set a numeric IPv6 token via GUI, which is why you will need
to add it manually in CLI using the above approach.</p>
<h2 id="port-forwards-traffic-rules-potato-potahtoh">
  <a class="heading-anchor" href="#port-forwards-traffic-rules-potato-potahtoh">Port forwards, traffic rules, potato, potahtoh<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Whenever you want to make a local machine accessible on the internet for IPv4, the solution is simple: set up a port
forward to that particular machine, and you&rsquo;re done! It&rsquo;s a common enough flow for people who&rsquo;ve set up game servers and
the like, and well understood by more novice users.</p>
<p>With IPv6, port forwards don&rsquo;t help. You&rsquo;ll have to check one tab over at &ldquo;Traffic rules&rdquo; in OpenWRT GUI.</p>
<p>It&rsquo;s a common misconception that by using IPv6 you are exposing everything to the world as each device gets its own IPv6
address, but turns out that this is not the case in most common setups. By default, OpenWRT forwards only a few types of
traffic to IPv6 hosts, such as ICMP packets that make <code>ping</code> work between devices over IPv6 across the public internet.
If you are interested in allowing IPv6 clients to access services on your local server that has an IPv6 address, you
will have to explicitly allow it by adding a new traffic rule.</p>
<p>There&rsquo;s one issue with this approach that a lot of users seem to run into: if the IPv6 prefix changes, then all my
traffic rules that are pointing to a particular host are automatically broken!</p>
<p>Luckily there is a clever workaround implemented on OpenWRT that bypasses this issue. Assuming that you followed the
previous step and set yourself up with a predictable IPv6 suffix, when setting up a traffic rule, set the target device
up as <code>::69/-64</code>, just replace <code>69</code> with your actual suffix. The IPv6 prefix can now change, but the ports that you&rsquo;ve
made accessible on this specific host will remain working.</p>
<p>At this point, you should be all set with a reasonably well working setup where you&rsquo;ve handled the issues with dynamic
IPv4 and IPv6 prefix, and you can access your services over the public internet even when things happen.</p>
<h2 id="limitations">
  <a class="heading-anchor" href="#limitations">Limitations<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>One issue that this setup has is the fact that DNS change propagation takes time. Usually clients will pick up the new
records within 5 minutes, but in my professional career I&rsquo;ve seen some clients take up to 24 hours or longer to finally
start sending traffic to the new DNS record. Whenever your IP address changes, there will be a mini-outage. Not
catastrophic if you&rsquo;re just hosting hobby projects and personal services at home, but I wouldn&rsquo;t host anything
mission-critical in such a setup.</p>
<p>When your OpenWRT device is as underpowered as mine, then you may notice that the TLS encryption overhead when <code>curl</code>
-ing around can be significant. I have set my dynamic DNS script to run every 5 minutes, and it shows up on the CPU
usage graphs on my router.</p>









<figure class="center">
  <a href="/posts/2026/05/06/self-host-at-home/media/graph.png">
    <img src="/posts/2026/05/06/self-host-at-home/media/graph_hu_e39ff7b6e73083d4.webp"
     width="956"
     height="383"
     loading="lazy"
     decoding="async"
     alt="CPU usage graph on my router showing the scheduled dynamic DNS script doing work.">

  </a>
  <figcaption class="center">CPU usage graph on my router showing the scheduled dynamic DNS script doing work.</figcaption>
</figure>

<h2 id="wireguard-all-the-things">
  <a class="heading-anchor" href="#wireguard-all-the-things">Wireguard all the things!<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I know that Tailscale is a popular method of connecting up your devices and making your personal services privately
accessible over that, which significantly reduces your attack surface. Being behind a few updates or not being vigilant
enough is less of an issue compared to exposing your services over the public internet.</p>
<p>You don&rsquo;t necessarily need Tailscale for that though! If you just need a way to access your services over a private and
secure network, then setting up a dedicated mini PC or single-board computer is a very good starting point. Let it be
the server, allow traffic to move between the clients over the Wireguard interface, and you&rsquo;re all set!</p>
<p>Alternatively, if you have an OpenWRT router, then you can do it right there, but I found the GUI management setup to be
a bit clunky compared to deploying the plain configuration files to clients. When I <em>did</em> do that test, I discovered
quickly that my router and its single ARM CPU core with no cryptography extensions is too slow for managing my Wireguard
network, with speeds topping out at 20 Mbit/s. <strong>20.</strong> The LattePanda IOTA can easily saturate its gigabit link, as does
the ThinkPad T430, and even devices like the Orange Pi Zero can handle a theoretical maximum of about 240 Mbit/s over
Wireguard measured using <a href="https://github.com/cyyself/wg-bench">wg-bench</a>.</p>
<p>My current Wireguard host is <a href="/posts/2026/04/04/lattepanda/">the LattePanda V1, the most unstable computer in my fleet.</a>
With a USB adapter, it can push almost half a gigabit of traffic over Wireguard.</p>
<p>If you&rsquo;re like me, and you like hosting your services over Docker or Podman, then instead of listening on ports for all
interfaces on your containers (default behaviour when setting up port forwards), I recommend listening only on the
Wireguard interface. This makes the service only accessible over Wireguard, meaning that you only need to set up one
port forward and traffic rule to connect to the Wireguard network, and then you have access to all of your services. The
attack surface is significantly reduced, the whole Wireguard solution is stable and very small, and unless you leak your
private key, you are reasonably secure!</p>
<p>Here&rsquo;s a snippet from a compose file showcasing how to set this up for IPv4 and IPv6:</p>
<pre tabindex="0"><code>ports:
  - 10.69.69.12:2283:2283
  - &#34;[fded:abba:acca::12]:2283:2283&#34;
</code></pre><p>Want to make the service available over Wireguard <em>and</em> over the local network directly? Just add those to the list!
Note that if your local address changes and you don&rsquo;t update it in the compose file, your container will refuse to start
up as it cannot listen to the interface any longer, but you can mitigate that with the static IP addresses step.</p>
<p>When you are going with this route, it is unlikely but still possible that by the time the container starts up, the
Wireguard interface is not yet up. To resolve this, you can use <code>systemd</code> to set Wireguard up as a dependency that you
will have to wait for before the container starts up.</p>
<p>I manage my Wireguard connection with <code>wg-quick@interfacename</code> service. You can set up a <code>systemd</code> override for Docker,
or if you manage your Docker/Podman services via systemd, then you can set it up per-service using this pattern:</p>
<pre tabindex="0"><code># /etc/systemd/system/myimmichserver.service.d/override.conf
[Unit]
Requires=wg-quick@interfacename.service
After=wg-quick@interfacename.service
</code></pre><p>By the way, <code>systemd</code> overrides are also really useful for ensuring that your storage that your containers rely on is
properly mounted. If my service requires the path <code>/immich</code> to be available and mounted, add something like this:</p>
<pre tabindex="0"><code>BindsTo=immich.mount
After=immich.mount
</code></pre><p>If you unmount the mount point, it will also properly bring down the service. The service won&rsquo;t start if the mount point
is missing. I&rsquo;ve had the issue with containers seeing blank mount points more times than I&rsquo;d like to admit, and this has
eliminated this issue for me.</p>
<p><code>systemd</code> has received a lot of hate online, and I don&rsquo;t think it&rsquo;s fair. The ease with which you can set up
dependencies on your system, set up resource limits, make services more restricted to improve the security posture is
great and allows me to and avoid all sorts of failure modes. Production services that I&rsquo;m responsible for make use of
these <code>systemd</code> features, with great results.</p>
<p>For services that need to be public, such as Nextcloud and its public shareable links, this approach won&rsquo;t work,
obviously, but for things that only you and your family members use, this is a viable approach.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This setup works well enough for me to confidently host my blog and self-hosted services off of it. I&rsquo;ve hit a lot of
paper cuts and frustrations along the way, but after following this guide, you don&rsquo;t have to do the same.</p>
<p>Yes, VLAN-s are intentionally missing from this guide. I&rsquo;ll get to them eventually, maybe by Q4 2037 given my lack of
free time.</p>
<p>And no, IPv6 isn&rsquo;t complicated, it&rsquo;s just different from what everyone is used to. If we started out with IPv6 right
from the get-go, <a href="https://www.ietf.org/archive/id/draft-thain-ipv8-00.html">we wouldn&rsquo;t be having dumb arguments online.</a></p>
]]></content:encoded></item><item><title>You can fake SSD-like disk speeds in any Linux VM, but it's unsafe (literally)</title><link>https://ounapuu.ee/posts/2026/04/08/ka-chow/</link><pubDate>Wed, 08 Apr 2026 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/04/08/ka-chow/</guid><description>Ka-chow!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/04/08/ka-chow/media/cover_hu_f29d29bcfd325b39.jpg" width="1200" height="630" alt="You can fake SSD-like disk speeds in any Linux VM, but it's unsafe (literally)" /><p>Do you have a need for <del>speed</del> really fast disk performance?</p>
<p>Are you unwilling or <a href="/posts/2026/03/01/cloud/">unable</a> to buy/rent a machine with fast, NVMe-based storage?</p>
<p>Are you OK with potential data corruption?</p>
<p>Then <code>cache=unsafe</code> is the solution to all your problems!</p>
<p>We had an interesting conundrum at work recently. Our platform does not use a lot of resources, but there are bursts of
activity that require a lot of CPU and performant disk IO from our infrastructure. This was previously handled by
manually starting some expensive AWS EC2 instances to cope with the load, but this manual process was error-prone due to
the human factor (which did end up causing an actual production outage once), and AWS is stupidly expensive for what you
get in return.</p>
<p>Around this time I also learned about a Proxmox server that we were underutilizing. My goal was to investigate the
resources that we had available and to ensure that we didn&rsquo;t have to think about taking any manual actions while at the
same time not relying on AWS and its expensive resources.</p>
<p>I set up a few VM-s on the Proxmox machine, and did some testing. CPU, memory, that was all fine, but the IO-bound
workloads that we had to run during those bursty periods would still be relatively slow. Not much slower than the main
infrastructure provider that we were using, but slow enough for a beefy machine to not be able to handle more than a few
parallel IO-heavy workloads running at the same time.</p>
<p>We exhausted a few other wild-ass ideas during the investigation:</p>
<ul>
<li>Docker on a RAM-backed storage drive
<ul>
<li>online resources did not inspire confidence in this working well, so we didn&rsquo;t try this</li>
</ul>
</li>
<li>optimizing the workload to not be IO-heavy
<ul>
<li>unsuccessful after spending a few hours on it, the high IO was a consequence of making an intentional trade-off to
reduce CPU load, and the IO requirement was much more manageable</li>
</ul>
</li>
<li>putting certain folders in the container itself on RAM-backed storage
<ul>
<li>highly container specific, and did not yield the desired results</li>
</ul>
</li>
</ul>
<p>Then one day I was browsing around Proxmox and noticed an interesting option on the virtual storage drives: setting the
cache mode to <code>unsafe</code>. With this one trick, your VM will see really fast disk speeds up to a certain point, and it&rsquo;s
invisible from the perspective of your workloads, no customization needed. In a way, this is like one of the RAM-backed
storage options, but for the whole VM.</p>
<p>The major trade-off is that an unexpected shutdown of the VM or the VM host will likely result in data corruption. This
is because you&rsquo;re writing everything to memory first, and <em>eventually</em> the writes will end up on persistent storage,
whenever the disks catch up with you. Something happens while changes are in memory, and they are lost.</p>
<p>In our case, the data corruption risk is completely OK, as the workloads are ephemeral, the results of the work are
sent to another machine immediately after completion, and the configuration of the machine is largely automated with
Ansible.</p>
<p>One instance of our workload would usually result in writing 50 MB to disk, and we observed about 300-500 IOPS of
performance from HDD-backed storage. The disks were not able to handle more than one at a time if we cared about
execution time.</p>
<p>With the <code>unsafe</code> trick, and on some relatively old hardware (assume DDR3 memory), we saw numbers as high as 15K IOPS
and disk throughput of 500+ MB/s. This was more than enough to handle peak loads, and the resources were always on and
available on a rented server with a stable price that compared extremely well to AWS.</p>
<p>Cloud service providers have their benefits, sure, but when all you need is raw speed and configurability to make it
happen, then owning a physical Linux server (or a few of them for redundancy) is a no-brainer, slam-dunk decision, as
long as you have someone in your team that knows how to manage one. Since you&rsquo;re working with Linux VM-s already in the
cloud, then you already have that person in your team, don&rsquo;t you? :)</p>
]]></content:encoded></item><item><title>The most unstable computer in my fleet is now the most critical one</title><link>https://ounapuu.ee/posts/2026/04/04/lattepanda/</link><pubDate>Sat, 04 Apr 2026 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/04/04/lattepanda/</guid><description>No way that this can go wrong. Not at all.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/04/04/lattepanda/media/cover_hu_73aa3329770b1e79.jpg" width="1200" height="630" alt="The most unstable computer in my fleet is now the most critical one" /><p>Remember <a href="/posts/2026/01/16/worst-media-server/">that failed experiment</a> where I ran Jellyfin off of a LattePanda V1?</p>
<p>Do you recall all the parts where I said what this single board computer <em><strong>cannot</strong></em> do?</p>
<p>Yeah, I remember.</p>
<p>Then I took it and put the two of the most critical services running on it: the blog you&rsquo;re reading right now, and my
Wireguard setup.</p>
<p>Trust me, it makes more sense with some context. The board is incapable of doing anything else other than serving
content from the eMMC module, and it has a functioning network port. It doesn&rsquo;t seem to crash in these scenarios.</p>
<p>When I try anything else with this board, especially things that include USB connectivity, things break. This makes the
board ideal for a light workload that needs to be up 24/7.</p>
<p>The biggest threat to my uptime is not internet connectivity or loss of power (although that did happen for the first
time in a year recently), it&rsquo;s me getting new ideas to try out on my setup, which results in downtime. This board is so
unreliable for trying those ideas out that it removes any and all temptation to <em>do</em> that, resulting in a computer that
has the highest chance of actually being up and running for a very long time.</p>
<p>To play things safe, I used an IKEA SJÖSS 20W USB-C power adapter that I got for 3 EUR, with a cheap USB-C to USB-A
adapter thrown into the mix. It looks janky, but the adapter outputs 5V 3A, which makes it the beefiest power adapter
that I have in my fleet for plain USB-A powered devices.</p>
<p>I then hit the board with some <code>stress</code> commands, including hitting the 2 GB of memory. It ran really well for days, no
issues at all.</p>









<figure class="center">
  <a href="/posts/2026/04/04/lattepanda/media/stressing-out.jpg">
    <img src="/posts/2026/04/04/lattepanda/media/stressing-out_hu_b4ea99889312878a.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Less espresso, more Lattepanda, more stresso.">

  </a>
  <figcaption class="center">Less espresso, more Lattepanda, more stresso.</figcaption>
</figure>

<p>I also improved the cooling situation. I am now a proud owner of an assortment of M2, M2.5 and M3 screws and bits, and
equipped with a Makita cordless drill, I made some mounting holes into an old aluminium server heat sink. The drilling
was a complete hack job, everything was misaligned, but it was good enough. Certainly better than holding the board and
heat sink together with thin velcro strips. The cooling performance is completely adequate, the board hits a maximum of
65°C with the heat sink facing down. This is well below the point at which the board starts to throttle its CPU.</p>









<figure class="center">
  <a href="/posts/2026/04/04/lattepanda/media/side-view.jpg">
    <img src="/posts/2026/04/04/lattepanda/media/side-view_hu_62184c91343891eb.webp"
     width="1000"
     height="482"
     loading="lazy"
     decoding="async"
     alt="Two out of three chips have adequate cooling. Whoops.">

  </a>
  <figcaption class="center">Two out of three chips have adequate cooling. Whoops.</figcaption>
</figure>

<p>The theoretical maximum Wireguard throughput on this board is about 340 Mbps, measured using the
fantastic <a href="https://github.com/cyyself/wg-bench">wg-bench</a> solution.</p>
<p>Remember the part about the USB ports being flaky? Yeah. That didn&rsquo;t stop me from getting a USB Gigabit Ethernet
adapter to remove one of the main limitations of the LattePanda V1. Based off of vibe-recommendations by Claude, I got a
TP-Link UE300 for its alleged low power usage and its availability at a local computer store in Estonia. It seems to
work well enough, you can push gigabit speeds through it measured by <code>iperf3</code>, and the actual Wireguard performance that
I could push through it with an actual workload was at about 420 Mbit/s, higher than indicated by the benchmark, and
plenty fast for most workloads, especially in external networks that are usually slower than that.</p>









<figure class="center">
  <a href="/posts/2026/04/04/lattepanda/media/speed.png">
    <img src="/posts/2026/04/04/lattepanda/media/speed_hu_553c4ae4b61a3ad.webp"
     width="1000"
     height="439"
     loading="lazy"
     decoding="async"
     alt="iperf3 test results on LattePanda V1, with occasional CPU and memory stress tests thrown in.">

  </a>
  <figcaption class="center">iperf3 test results on LattePanda V1, with occasional CPU and memory stress tests thrown in.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2026/04/04/lattepanda/media/wireguard.png">
    <img src="/posts/2026/04/04/lattepanda/media/wireguard_hu_b67d71a1d5528ffb.webp"
     width="1000"
     height="439"
     loading="lazy"
     decoding="async"
     alt="Copying data from another Wireguard peer through the LattePanda V1.">

  </a>
  <figcaption class="center">Copying data from another Wireguard peer through the LattePanda V1.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2026/04/04/lattepanda/media/cables.jpg">
    <img src="/posts/2026/04/04/lattepanda/media/cables_hu_d0b5c96d42223007.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Cable management is not my strength.">

  </a>
  <figcaption class="center">Cable management is not my strength.</figcaption>
</figure>

<p>A few hours after making that
change, <a href="https://news.ycombinator.com/item?id=47597159">a HN post put some mild load on the LattePanda V1,</a> what good
timing.</p>
<p>As of publishing this post, the blog has been running mostly off of the LattePanda V1 for over a month now, with that
gap in it being caused by contemplating getting that USB Ethernet adapter and temporarily running the blog and Wireguard
off of another mini PC during that time.</p>
<p>Did you notice?</p>
<h2 id="2026-july-update">
  <a class="heading-anchor" href="#2026-july-update">2026 July update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I was running out of room and network ports on my router, so I decided to stop this experiment. During all this time,
there were no issues with the LattePanda V1, except when I accidentally bumped into its power cable and made it go
offline. Oops.</p>
]]></content:encoded></item><item><title>Server room? No, I have a server pantry.</title><link>https://ounapuu.ee/posts/2026/03/11/server-pantry/</link><pubDate>Wed, 11 Mar 2026 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/03/11/server-pantry/</guid><description>Who needs AI data centers when you can have this?</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/03/11/server-pantry/media/cover_hu_37ffc79125a38881.jpg" width="1200" height="630" alt="Server room? No, I have a server pantry." /><p>The apartment that I live in right now has two small rooms with doors on them.</p>
<p>One of them is like a normal closet and that&rsquo;s where the ISP passive fiber optic line comes in.</p>
<p>The other one is a similarly sized room with a bunch of shelves and ventilation to keep things cool. A pantry,
basically.</p>
<p>I&rsquo;ve used the closet as a networking and home server spot for a while now, with a small dedicated shelf holding
everything. That shelf was a bit limiting, it could not accommodate all of my hardware that I wanted to play around
with, and the closet did not have very good ventilation, which resulted in the top half of the closet getting notably
warm during summer months. Not <em>too</em> warm, but warm enough to feel it when opening the closet.</p>
<p>One day I decided to realize an idea that had been in my mind ever since I
started <a href="/posts/2025/12/15/construction-vs-software/">renovating</a> this apartment: turn the pantry into a server room.</p>
<p>Meet the server pantry.</p>









<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/vent-1.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/vent-1_hu_730f40ee189b0b5b.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Vent from the pantry to the closet, where all the networking gear and power is.">

  </a>
  <figcaption class="center">Vent from the pantry to the closet, where all the networking gear and power is.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/vent-2.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/vent-2_hu_51fc177be5661433.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Hello there.">

  </a>
  <figcaption class="center">Hello there.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/vent-3.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/vent-3_hu_49ffe0faa0ae045b.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Power and network, installed by a professional tool.">

  </a>
  <figcaption class="center">Power and network, installed by a professional tool.</figcaption>
</figure>

<p>It&rsquo;s cool.</p>
<p>It&rsquo;s the furthest point in the apartment from the bed and my home office setup, so I can put incredibly noisy computers
in it.</p>
<p>It only has a few spiders.</p>









<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/pantry-dankpad.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/pantry-dankpad_hu_6ba2594216218238.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="ThinkPad T430 (the server) chilling in the pantry.">

  </a>
  <figcaption class="center">ThinkPad T430 (the server) chilling in the pantry.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/pantry-iota.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/pantry-iota_hu_a4b96ecec163f97f.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="LattePanda IOTA, chilling in the pantry, below an IKEA Variera shelf thingy to fit more compute power on the shelf in
the near future.">

  </a>
  <figcaption class="center">LattePanda IOTA, chilling in the pantry, below an IKEA Variera shelf thingy to fit more compute power on the shelf in
the near future.</figcaption>
</figure>

<p>Due to the pantry being cool and dry, it makes for a good spot for hosting food and stuff. Adding &lt;100W of
heat output at the top of the room should not be an issue as hot air tends to rise, and if temperatures end up being an
issue, I can open one of the two vents that are directly connected to the outside to get some fresh and cool air in. The
temperature delta between the bottom and top of the pantry seems to be about 10°C, ranging from 6-16°C.</p>
<p>The impact of running things in a slightly chillier room is noticeable on the temperature sensors of the hardware that I
put in there. A PC with overkill CPU cooler on an Intel i5-10500 did report 16°C CPU core temperatures at one point when
idling, compared to 20-24°C when running in a cold corner in the living room. The LattePanda IOTA hit 30°C on the CPU
cores. Hard drives hover around 30-37°C, with a maximum of 40-44°C.</p>
<p>It&rsquo;s pretty cool.</p>









<figure class="center">
  <a href="/posts/2026/03/11/server-pantry/media/disco.jpg">
    <img src="/posts/2026/03/11/server-pantry/media/disco_hu_e5969bb832af63d7.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Party hard.">

  </a>
  <figcaption class="center">Party hard.</figcaption>
</figure>

<h2 id="2026-june-update">
  <a class="heading-anchor" href="#2026-june-update">2026 June update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;ve now moved away from this concept due to Summer being a thing. Beer got too warm in there with 60-110 W of compute
equipment being in there.</p>
]]></content:encoded></item><item><title>The cloud just stopped scaling</title><link>https://ounapuu.ee/posts/2026/03/01/cloud/</link><pubDate>Sun, 01 Mar 2026 17:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/03/01/cloud/</guid><description>Future post on this blog: why my home server is 'production' now.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/03/01/cloud/media/cover_hu_c2677f96f335e732.jpg" width="1200" height="630" alt="The cloud just stopped scaling" /><p>It has happened.</p>
<p><a href="https://status.hetzner.com/incident/0a75c7ae-3377-41dc-aabe-601063724d24">The cloud just stopped scaling.</a></p>
<p>Hetzner&rsquo;s cloud, for now.</p>
<p>At this rate, my home server will actually have to become production at work, and
<a href="/posts/2025/12/01/steam-machine/">my gaming PC</a> has to be converted to a server because it has a whopping 32 GB of
RAM and 6 good CPU cores.</p>
<p>With <a href="https://store.steampowered.com/app/2483190/Forza_Horizon_6/">Forza Horizon 6</a> on the <em>horizon</em>, it is time for
some difficult decisions&hellip;</p>
<h2 id="2026-03-02-update">
  <a class="heading-anchor" href="#2026-03-02-update">2026-03-02 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Shortly after publishing this
post, <a href="https://www.404media.co/amazon-data-centers-on-fire-after-iranian-missile-strikes-on-dubai/">AWS had a different type of issue with availability zones going down</a>
due to&hellip; Iranian missile strikes. I&rsquo;ve wanted decentralized hosting to be more popular, but <em><strong>not like this.</strong></em></p>
]]></content:encoded></item><item><title>I built the worst Jellyfin media server</title><link>https://ounapuu.ee/posts/2026/01/16/worst-media-server/</link><pubDate>Fri, 16 Jan 2026 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2026/01/16/worst-media-server/</guid><description>This experiment is brought to you by absurd memory prices.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2026/01/16/worst-media-server/media/cover_hu_dd22e2bc1424d67c.jpg" width="1200" height="630" alt="I built the worst Jellyfin media server" /><p>LattePanda V1. <a href="/posts/2023/02/28/lattepanda-v1/">It&rsquo;s been a while, huh?</a></p>
<p>I had it as a backup server <a href="/posts/2023/06/10/how-i-blew-up-my-backup-server/">(which I blew up)</a>.</p>
<p>Then it got promoted to&hellip; <a href="/posts/2024/12/11/wireguard-backup-fleet/">a backup server.</a> But
then <a href="/posts/2024/12/11/wireguard-backup-fleet/media/lattepanda-psu-failure.png">its PSU blew up.</a></p>
<p>Then it was waiting for some cool ideas at <a href="https://kaurpalang.com/">a potato enthusiast.</a></p>
<p>Now it&rsquo;s back in my hands.</p>
<p><a href="/posts/2025/11/18/lattepanda-iota/">Unlike its modern counterpart,</a> the LattePanda V1 is a flawed single board
computer.</p>
<p>It&rsquo;s slow.</p>
<p>It&rsquo;s unstable if you connect power hungry USB devices to it.</p>
<p>It needs some cooling, but I&rsquo;m too cheap to buy a properly designed heat sink for it.</p>
<p>It has display quirks.</p>
<p>It only has a slow 100 Mbps Ethernet link.</p>
<p>It only seems to work reliably on one side. Not even joking, the &ldquo;heat sink down&rdquo; configuration is the only one that
works for me.</p>
<p><a href="https://libreelec.tv/">LibreELEC</a> failed to play back any videos on it properly. The videos would play for 10 seconds,
and then it would hang, no matter the encoding or hardware acceleration settings.</p>
<p>With hardware prices being wonky again, I decided to give this board a last chance of being useful. If new hardware is
absurdly expensive, then it makes perfect sense to use what you have, no matter how slow or crummy it might be. Reduce,
reuse, and only <em>then</em> recycle.</p>
<p>That&rsquo;s when I decided to run a Jellyfin server off of it. Transcoding is out of the question, but serving media files
over the network should still be quick enough, right?</p>
<p>For this experiment, I
used <a href="/posts/2025/10/06/datablocks-white-label-drives/">one of the 18 TB hard drives that I&rsquo;ve covered earlier.</a>
Just the single one, no redundancy here. This one drive is probably about 10x the cost of the LattePanda V1 itself,
making it a perfectly reasonable choice.</p>
<p>For ease of troubleshooting, debugging and guaranteed eventual reinstallation, I put Fedora Server on an 128 GB USB 3.0
flash drive by Samsung. <a href="/posts/2024/12/02/linux-on-usb/">Risky move, I know,</a> but as you might have noticed, this whole
build is everything <em>but</em> reasonable. That left the eMMC storage as the perfect candidate for storing cache and service
related files.</p>
<p>Cooling is solved by a random server heat sink slapped on the bottom of the LattePanda, with a few critical
components like the CPU making contact with thick and soft thermal pads. The whole thing is fastened using velcro strips
that I cut to a thin size in the middle so that I can route it between the components on the PCB and within the heat
sink fins. The edges of the heat sink are covered with some painters&rsquo; tape that I had around to avoid shorting anything
out on the board, because those parts on the board contain all sorts of metal bits and pins that have power going
through them. I&rsquo;m actually quite happy with that mount!</p>









<figure class="center">
  <a href="/posts/2026/01/16/worst-media-server/media/lattepanda-temps.png">
    <img src="/posts/2026/01/16/worst-media-server/media/lattepanda-temps_hu_84c5210842d31066.webp"
     width="1000"
     height="683"
     loading="lazy"
     decoding="async"
     alt="All things considered, the janky cooling setup is holding up very well. The 100 degree peaks are sensor/measurement
errors.">

  </a>
  <figcaption class="center">All things considered, the janky cooling setup is holding up very well. The 100 degree peaks are sensor/measurement
errors.</figcaption>
</figure>

<p>I&rsquo;ve been experimenting with Podman again after Docker kept doing weird things with the v29 release, and I&rsquo;ve been happy
with the results, so that&rsquo;s what I used on the LattePanda V1 as well. I slapped Jellyfin on it, threw in some test files
and gave it a go.</p>
<p>Navigating the UI feels a bit slow at times, but it&rsquo;s not really noticeable on an LG smart TV with a really laggy user
interface.</p>
<p>Actual video playback that requires no transcoding works quite well, at least for smaller media sizes.</p>
<p>Technically, you can do transcoding on this and even utilize the tiny little integrated GPU in it, but the results are
not usable. With smaller files it might be usable, but in one test I saw 7-8 FPS transcoding speeds and the server
struggling to keep up, with CPU usage locked at 100%.</p>
<p>If we ignore all the downsides, then the LattePanda V1 can actually be a usable media server. Serving files off of a big
drive does not require a lot of resources, and for that the LattePanda V1 is a solid choice. It also uses only a few
watts of power on its own, so you can keep it on 24/7 guilt-free. In this build, the hard drive itself is actually the
most power hungry component by a long shot (about 2/3 of the total power budget).</p>
<p>The 2 GB of memory is <em>juuuuuuuust</em> enough for this setup.</p>









<figure class="center">
  <a href="/posts/2026/01/16/worst-media-server/media/lattepanda-memory-usage.png">
    <img src="/posts/2026/01/16/worst-media-server/media/lattepanda-memory-usage_hu_ad0b4de22af0ece1.webp"
     width="1000"
     height="683"
     loading="lazy"
     decoding="async"
     alt="Totally usable.">

  </a>
  <figcaption class="center">Totally usable.</figcaption>
</figure>

<p>As of writing this post, it has been running for about a week, and it&rsquo;s been fine. I intend to keep it running in a
drawer for as long as possible just to see what will die first.</p>
<p>Will it be the eMMC storage?</p>
<p>The USB flash drive holding the operating system?</p>
<p>The expensive hard drive?</p>
<p>The power supply?</p>
<p>The thin velcro strips holding the cooling together?</p>
<p>My patience?</p>
<p>Don&rsquo;t worry, I have backups. <em>Well</em>, backups of the important bits. I&rsquo;m ready to lose
data <a href="/posts/2026/01/14/raid0/">again.</a></p>
<h2 id="2026-01-22-update">
  <a class="heading-anchor" href="#2026-01-22-update">2026-01-22 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Okay, it was <em>too</em> bad of an idea.</p>
<p>The LattePanda V1 would occasionally just&hellip; stop.</p>









<figure class="center">
  <a href="/posts/2026/01/16/worst-media-server/media/lattepanda-is-kill.png">
    <img src="/posts/2026/01/16/worst-media-server/media/lattepanda-is-kill_hu_26193b745dd0bf59.webp"
     width="1000"
     height="507"
     loading="lazy"
     decoding="async"
     alt="Oops, it died.">

  </a>
  <figcaption class="center">Oops, it died.</figcaption>
</figure>

<p>From what I gathered by accident, it&rsquo;s likely that the USB port containing the operating system would flake out and
result in the system not being able to run any tools that are not in memory. I tried to move the installation to the
eMMC drive, but after failing multiple times due to the display not working, or the system deciding to shut down
randomly, I gave up on it. For now.</p>
<p>Guess I&rsquo;ll have to use it in a solar-powered website project. ¯\_(ツ)_/¯</p>
]]></content:encoded></item><item><title>LattePanda IOTA review: how does it perform as a home server?</title><link>https://ounapuu.ee/posts/2025/11/18/lattepanda-iota/</link><pubDate>Tue, 18 Nov 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/11/18/lattepanda-iota/</guid><description>I received a review sample of the LattePanda IOTA, here's what I did to it.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/11/18/lattepanda-iota/media/cover_hu_ee50a0b402f18b9b.jpg" width="1200" height="630" alt="LattePanda IOTA review: how does it perform as a home server?" /><p><em><strong>Disclosure:</strong></em> the review sample was provided by <a href="https://www.dfrobot.com/">DFRobot, the makers of LattePanda.</a> I am
allowed to keep the review sample indefinitely, no money exchanged hands, and as always, this post covers my own
thoughts and views on the product.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p><a href="/posts/2023/02/28/lattepanda-v1/">In 2023, I happened to find a LattePanda V1 for sale at a good price.</a> Given the
then-poor availability of affordable Raspberry Pi units, I got one for testing and finding potential use cases for it in
my setup. However, it was just a little bit too weak for any practical uses in 2023, with its CPU and USB connectivity
being just slow enough to be of less use, and the networking being capped at 100 Mbit/s.</p>
<p>In 2025, we have the spiritual successor to it: <a href="https://www.lattepanda.com/lattepanda-iota">the LattePanda IOTA.</a>
It keeps the same form factor, but the connectivity and raw power have all received a significant jump, with the CPU
performance rivalling my current home server, <a href="/posts/2024/10/16/third-times-the-charm/">the trusty ThinkPad T430.</a></p>
<p>The marketing materials list all sorts of sensible use cases for it. I&rsquo;m sure that it works fine for those, but I&rsquo;m only
interested in one thing: how close does this board get to
being <a href="/posts/2025/03/07/perfect-home-server/">the perfect home server?</a></p>
<blockquote>
<p>The perfect home server uses very little power, offers plenty of affordable storage and provides a lot of performance
when it’s actually being relied upon.</p>
</blockquote>
<blockquote>
<p>In my case, low power means less than 5 W while idling, 10+ TB of redundant storage for data resilience and integrity
concerns, and performance means about 4 modern CPU cores’ worth (low-to-midrange desktop CPU performance).</p>
</blockquote>
<h2 id="the-model-and-accessories">
  <a class="heading-anchor" href="#the-model-and-accessories">The model and accessories<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The model I&rsquo;m reviewing is the 8GB RAM/64GB eMMC one, with a Windows 11 installation on it (not activated).</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-0_hu_c45484277466acf6.webp"
     width="1000"
     height="774"
     loading="lazy"
     decoding="async"
     alt="The LattePanda IOTA.">

  </a>
  <figcaption class="center">The LattePanda IOTA.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-1_hu_d3a2ee51a8a3f4c3.webp"
     width="1000"
     height="686"
     loading="lazy"
     decoding="async"
     alt="My wife said that the logo for the LattePanda is cute. I agree.">

  </a>
  <figcaption class="center">My wife said that the logo for the LattePanda is cute. I agree.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-2.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-2_hu_cae36972b32803a8.webp"
     width="1000"
     height="556"
     loading="lazy"
     decoding="async"
     alt="Side view, including the PCIe x1 connector.">

  </a>
  <figcaption class="center">Side view, including the PCIe x1 connector.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-3.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-3_hu_4b383f3738800b2.webp"
     width="1000"
     height="540"
     loading="lazy"
     decoding="async"
     alt="Side view, with GPIO connections prominent.">

  </a>
  <figcaption class="center">Side view, with GPIO connections prominent.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-4.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-4_hu_94feb7c0302ce393.webp"
     width="1000"
     height="626"
     loading="lazy"
     decoding="async"
     alt="Side view, including USB-C PD-compatible port, microSD card reader, a port forgotten by all smartphone makers, and
gigabit Ethernet.">

  </a>
  <figcaption class="center">Side view, including USB-C PD-compatible port, microSD card reader, a port forgotten by all smartphone makers, and
gigabit Ethernet.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/lattepanda-5.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/lattepanda-5_hu_449bf0ed42b37f87.webp"
     width="1000"
     height="661"
     loading="lazy"
     decoding="async"
     alt="Side view, including three USB 3 10 Gbps ports, and a full-sized HDMI port.">

  </a>
  <figcaption class="center">Side view, including three USB 3 10 Gbps ports, and a full-sized HDMI port.</figcaption>
</figure>

<p>Along with the review unit itself, I got sent the following accessories:</p>
<ul>
<li><a href="https://www.dfrobot.com/product-2987.html">active cooler</a></li>
<li><a href="https://www.dfrobot.com/product-2985.html">M.2 M-key expansion board</a></li>
<li><a href="https://www.dfrobot.com/product-2984.html">51W PoE expansion board</a></li>
<li><a href="https://www.dfrobot.com/product-2982.html">M.2 4G LTE expansion board</a></li>
<li><a href="https://www.dfrobot.com/product-2983.html">UPS expansion board</a></li>
</ul>
<p>The board was tested with a Lenovo 65W USB-C power adapter, because that&rsquo;s what I had available. Given the specs of the
board and the accessories, that should be plenty. As far as I know, USB power delivery seems to work fine and it&rsquo;s not
just a weird USB-C connector that requires specific voltages to work.</p>
<p>The M.2 NVMe SSD used in this review is a 512 GB Samsung PM9A1. I got that one from another PC that really didn&rsquo;t need a
boot drive that large.</p>
<p>Most of the testing was done with a fresh Fedora Server 43 installation, kernel version 6.17.7.</p>
<h2 id="the-hardware">
  <a class="heading-anchor" href="#the-hardware">The hardware<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I suggest looking at <a href="https://www.lattepanda.com/lattepanda-iota#spec">the spec sheet</a> if you&rsquo;re interested in all the
fine details and available configurations.</p>
<p>In short:</p>
<ul>
<li>CPU: Intel N150, 4 cores, 4 threads, up to 3.6 GHz</li>
<li>RAM: 8/16 GB (depending on model)</li>
<li>Onboard storage: 64/128GB eMMC (depending on model)</li>
<li>Networking: gigabit Ethernet port</li>
<li>Real-time clock: <em><strong>yes!</strong></em></li>
</ul>
<p>The overall connectivity has been improved with the new version of this board compared to the old board. The USB ports
are all fast 10 Gbit/s ones, and we have actual PCIe connectivity to play with, although the available bandwidth is
quite limited with a PCIe 3.0 x1 lane available on the port that both the M.2 M-key and PoE adapter connect to.</p>
<p>What caught my eye was the CPU performance I&rsquo;ve been proudly
running <a href="/posts/2024/10/16/third-times-the-charm/">an old ThinkPad T430</a> as a server for a while now, with some failed
attempts to find a more <a href="/posts/2023/10/09/zimaboard/">low-power</a>
and <a href="/posts/2025/06/06/thinkcentre-m900-tiny/">efficient</a>
solution.</p>
<p>The Intel N150 is now offering similar levels of performance, but in a much smaller power envelope.</p>
<p>When it comes to more specialized functionalities, such as GPIO and the RP2040 microcontroller, I don&rsquo;t currently have a
solid use case for them, so they won&rsquo;t be covered in this review. I might fancy giving them a go in the future though,
it would be nice to get some environmental sensors on it to monitor the temperature and humidity of the server room
(which is a closet).</p>
<p>Since I also don&rsquo;t have an 4G LTE modem available, I did not test the associated adapter.</p>
<h2 id="m2-m-key-adapter">
  <a class="heading-anchor" href="#m2-m-key-adapter">M.2 M-key adapter<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The way you can add expansion boards to the LattePanda IOTA is quite similar to how Raspberry Pi 5 and other similar
single board computers do it: you simply run a flexible cable to an adapter board, and bam, you have extra
connectivity!</p>
<p>With the M.2 M-key adapter kit, you get the adapter itself, some mounting screws and brass stand-offs, and a tiny little
flexible cable for the PCIe signal.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-0_hu_db0b0dd1c31ad3b0.webp"
     width="1000"
     height="632"
     loading="lazy"
     decoding="async"
     alt="Packaging of the M.2 M-key adapter.">

  </a>
  <figcaption class="center">Packaging of the M.2 M-key adapter.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-1_hu_44b0dab8db46a0b8.webp"
     width="1000"
     height="556"
     loading="lazy"
     decoding="async"
     alt="The adapter itself.">

  </a>
  <figcaption class="center">The adapter itself.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-2.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-2_hu_4a68666849c39eb2.webp"
     width="1000"
     height="450"
     loading="lazy"
     decoding="async"
     alt="Bottom of the adapter (or top, depending on how you mount it).">

  </a>
  <figcaption class="center">Bottom of the adapter (or top, depending on how you mount it).</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-installed-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-installed-0_hu_b7a06679bf9193a6.webp"
     width="1000"
     height="785"
     loading="lazy"
     decoding="async"
     alt="Adapter installed to the SBC.">

  </a>
  <figcaption class="center">Adapter installed to the SBC.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-installed-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/m2-adapter-installed-1_hu_37d9a777355bca8f.webp"
     width="1000"
     height="718"
     loading="lazy"
     decoding="async"
     alt="Adapter with an M.2 2280 NVMe SSD. This Western Digital SSD was used for some quick testing.">

  </a>
  <figcaption class="center">Adapter with an M.2 2280 NVMe SSD. This Western Digital SSD was used for some quick testing.</figcaption>
</figure>

<p>The link speed is PCIe 3.0, with one lane available. In theory, this means a maximum of 1 GB/s of throughput. In
practice and with this board and SSD combination, I got a maximum of ~810 MB/s. I expect some levels of losses with
these types of setups, so in my view this seems normal. For the test, I just did
a <code>dd if=/dev/nvme0n1 of=/dev/null bs=8M status=progress</code>. The SSD itself supports up to 4 lanes of PCIe connectivity so
that should not be a limiting factor here.</p>
<p>The lovely part about M.2 NVMe ports is that you can use it for a lot of off-label use cases.</p>
<p>Fancy some SATA ports? There&rsquo;s an <a href="https://www.dfrobot.com/product-2811.html">adapter</a> for that.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Or a network card? Some fancy AI accelator thingy? Or a full-sized GPU? Anything will work (probably), as long as the
cables and adapters are high quality, and you provide extra power to the device through other means.</p>
<h2 id="poe-expansion-board">
  <a class="heading-anchor" href="#poe-expansion-board">PoE expansion board<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The only device on my network that is connected over PoE is currently an Ubiquiti Wi-Fi access point, and that is
unlikely to change in the near future because that would require a full replacement of my networking gear.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<p>However, I still gave this board a quick go, and I&rsquo;m happy to report that it also works as an additional standalone
Ethernet port. The Ethernet controller seems to be similar or the same as on the main board, and it shows up as a
separate networking device. Both are Realtek
NIC-s (<code>Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller</code>), and they work
with the <code>r8169</code> driver. Realtek has a spotty compatibility story overall on Linux from what I&rsquo;ve read, but this one
seems to work fine on Fedora Server 43.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/poe-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/poe-0_hu_228bfca3cc169a2d.webp"
     width="1000"
     height="746"
     loading="lazy"
     decoding="async"
     alt="PoE adapter.">

  </a>
  <figcaption class="center">PoE adapter.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/poe-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/poe-1_hu_7365b2a8e90261be.webp"
     width="1000"
     height="780"
     loading="lazy"
     decoding="async"
     alt="PoE adapter, other side.">

  </a>
  <figcaption class="center">PoE adapter, other side.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/poe-2.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/poe-2_hu_f73e8ff578bc9f0d.webp"
     width="1000"
     height="816"
     loading="lazy"
     decoding="async"
     alt="PoE adapter, installed.">

  </a>
  <figcaption class="center">PoE adapter, installed.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/poe-3.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/poe-3_hu_7ab3c58ff5a4560.webp"
     width="1000"
     height="551"
     loading="lazy"
     decoding="async"
     alt="Detected network interfaces on Fedora Server 43. Both work!">

  </a>
  <figcaption class="center">Detected network interfaces on Fedora Server 43. Both work!</figcaption>
</figure>

<p>I was very close to pulling the trigger and turning it into a beefy router so that I can finally move my Wireguard
networks on the router as my current one cannot do more than 20 Mbit/s of Wireguard traffic, but I didn&rsquo;t end up going
through with that idea because of how well the SBC did in other areas.</p>
<h2 id="ups-expansion-board">
  <a class="heading-anchor" href="#ups-expansion-board">UPS expansion board<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>As some of you might know, I&rsquo;m a fan
of <a href="/posts/2025/08/18/cheap-power-banks-suck/">playing with fir-</a> 18650 Li-ion battery cells, and I&rsquo;m
hoping to one day build a <a href="https://solar.lowtechmagazine.com/">solar-powered server of my own</a> (of which there
are <a href="https://louwrentius.com/i-made-my-blog-solar-powered-then-things-escalated.html">many</a> <a href="https://dri.es/my-solar-powered-and-self-hosted-website">examples</a>).</p>
<p>I took some spare 18650 cells that came from an old ThinkPad battery, made sure that the voltages are more-or-less
the same, and threw them on the board.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/ups-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/ups-0_hu_866496dcf875ef62.webp"
     width="1000"
     height="809"
     loading="lazy"
     decoding="async"
     alt="UPS adapter.">

  </a>
  <figcaption class="center">UPS adapter.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/ups-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/ups-1_hu_7e7014640b9e0ab1.webp"
     width="1000"
     height="728"
     loading="lazy"
     decoding="async"
     alt="UPS adapter, other side.">

  </a>
  <figcaption class="center">UPS adapter, other side.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/ups-2.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/ups-2_hu_fca2886a8254bb77.webp"
     width="1000"
     height="886"
     loading="lazy"
     decoding="async"
     alt="UPS adapter, installed on the board.">

  </a>
  <figcaption class="center">UPS adapter, installed on the board.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/ups-3.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/ups-3_hu_5f85831f1acaa04.webp"
     width="1000"
     height="893"
     loading="lazy"
     decoding="async"
     alt="UPS adapter, running off of batteries.">

  </a>
  <figcaption class="center">UPS adapter, running off of batteries.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/ups-4.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/ups-4_hu_7f9dc3c2894a962a.webp"
     width="1000"
     height="851"
     loading="lazy"
     decoding="async"
     alt="UPS adapter, charging.">

  </a>
  <figcaption class="center">UPS adapter, charging.</figcaption>
</figure>

<p>Connecting the UPS board with the standoffs was fine, but the cable connecting it
with the SBC was finicky. I triple-checked that the connector was the right way, but had to still use an uncomfortable
amount of force to connect it all up. The battery cells themselves sit snugly on the board, and unless you drop the
board, they should not fall out on their own. You&rsquo;d still want to build a case around it if you&rsquo;re going to actually put
it to use in rough environments.</p>
<p>The manual for the UPS board emphasizes that it only works on Windows 10/11, and sadly that seems to be the case, the
UPS does not seem to show up as an USB-listed device, and tools like <a href="https://networkupstools.org/">NUT</a> did not find
anything to monitor with a quick 5-minute investigation.</p>
<p>The UPS board also has an interesting selection of switches that you can use to adjust the behaviour of the board, like
automatically turning the board on when power comes back on, and setting an 80% battery charge limit. The first one was
not really necessary to use, the board would follow whatever setting you have enabled on the SBC itself. I configured
mine via UEFI settings to automatically turn on with a power adapter connected, and that worked here as well.</p>
<p>The run time of your LattePanda IOTA with the UPS expansion board will heavily depend on your workloads and quality of
your battery cells. Mine were used cells, and then I hit the board with <code>stress -c 4</code> to create some load on it. It ran
for over an hour like that, and then I got bored and wanted to proceed with testing other accessories. The marketing
materials mention up to 8 hours of runtime, and I suspect that with good Li-ion cells and workloads where you idle most
of the time, it will likely be achievable.</p>
<p>The board seems to trigger a hard shutdown on Linux because the host OS is not aware of a battery being connected. Not
that catastrophic for most modern filesystems and database engines, but something to consider in your own workloads in
case they are Linux-based.</p>
<p>The UPS board seems to handle power connection and disconnection events well enough, it did not do anything weird when
repeatedly plugging and unplugging the USB-C cable.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<p>Based on the readings from a wall outlet energy meter, the board uses up to 20W when charging the cells. It&rsquo;s possible
for the board to pull more than that with a maximum CPU load and connected peripherals, so I wonder if that may be an
issue with more intense usage scenarios.</p>
<p>During charging and discharging cycles, even under heavy loads, the battery cells did not get hot and were at best warm
to touch.</p>
<h2 id="ethernet">
  <a class="heading-anchor" href="#ethernet">Ethernet<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s gigabit.</p>
<p>Fine for my use case given that I still live in 2006 and only have devices that support gigabit Ethernet
speeds at best (excluding the Ubiquiti Wi-Fi AP), but certainly less
than <a href="https://www.zimaspace.com/products/single-board2-server#specs">some competing products.</a></p>
<h2 id="emmc-and-usb-storage">
  <a class="heading-anchor" href="#emmc-and-usb-storage">eMMC and USB storage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Compared to the LattePanda V1, the USB port performance is actually decent for my use case. I can connect up to three
USB-connected storage devices to the board, so that&rsquo;s exactly what I did.</p>
<p>I set up three different USB-connected devices:</p>
<ul>
<li>USB hard drive (Seagate Basic)</li>
<li>USB SATA SSD (Samsung QVO 4TB in ICY BOX USB-SATA adapter)</li>
<li>USB NVMe SSD (512 GB Samsung PM9A1 with some random cheap USB to M.2 NVMe adapter)</li>
</ul>
<p>For each device (including on-board eMMC device), I ran
a <code>while true; do dd if=/dev/X of=/dev/null bs=8M status=progress; sleep 5; done</code>, which puts a sequential
read workload on all the drives in an infinite loop.</p>
<p>After about 72 TB of data read in less than 24 hours, I checked the kernel logs and there were no stability issues
whatsoever. The NVMe SSD started throttling due to heat, which was expected with that cheap adapter.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/storage-stress-test.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/storage-stress-test_hu_fe28dcd9ae42d4a9.webp"
     width="1000"
     height="437"
     loading="lazy"
     decoding="async"
     alt="Results of the storage stress test.">

  </a>
  <figcaption class="center">Results of the storage stress test.</figcaption>
</figure>

<p>Assuming no issues with any cables and adapters, the USB ports seem to be solid enough for running storage devices off
of. Yes, <a href="/posts/2025/06/06/thinkcentre-m900-tiny/#2025-06-08-update">it can be a horrible idea in some use cases,</a> but
at the same time my ThinkPad T430 has been excellent with USB-based storage, and that&rsquo;s with one of the USB ports being
coffee-stained!</p>
<p>The eMMC chip is also more performant compared to the previous iteration, with sequential read speeds averaging around
316 MB/s, writes around 175 MB/s, and average read latency being around 0.15 ms. Certainly good enough for a boot drive.</p>
<h2 id="display-connectivity">
  <a class="heading-anchor" href="#display-connectivity">Display connectivity<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The LattePanda V1 struggled with larger displays, and when I gave it a go during this review, it would not properly
display an image on my 3440x1440p monitor.</p>
<p>The LattePanda IOTA just did it, at 60 Hz. On Fedora Workstation and GNOME, the experience was smooth. Once you start
doing things in the browser, like video playback, the situation is less optimal, but as a makeshift desktop PC it is
alright for most low/mid-range activities.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/display-output.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/display-output_hu_b30923cd36a81fa0.webp"
     width="1000"
     height="712"
     loading="lazy"
     decoding="async"
     alt="The display output working as intended on Windows 11.">

  </a>
  <figcaption class="center">The display output working as intended on Windows 11.</figcaption>
</figure>

<h2 id="windows-compatibility">
  <a class="heading-anchor" href="#windows-compatibility">Windows compatibility<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The board came with a Windows 11 installation (not activated). As is tradition with Windows, the initial impressions are
horrible, update processes running in the background made the active cooler go wild and the device felt sluggish.</p>
<p>But after that process is done, the experience is not bad at all if you look past the OS being Windows.</p>
<p>I did not do a thorough investigation and I suggest formatting the device boot drive either way when receiving it, but
the Windows 11 installation looked clean enough, with no obvious bloatware.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/windows-experience.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/windows-experience_hu_bd5f1e67dc619872.webp"
     width="1000"
     height="760"
     loading="lazy"
     decoding="async"
     alt="The typical Windows experience.">

  </a>
  <figcaption class="center">The typical Windows experience.</figcaption>
</figure>

<h2 id="linux-compatibility">
  <a class="heading-anchor" href="#linux-compatibility">Linux compatibility<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The LattePanda V1 had some quirks. The performance was iffy, and you had to specify a Linux kernel parameter on first
boot so that Fedora Linux does not confuse the optional display interface to be an always-connected primary display.</p>
<p>The previous version also didn&rsquo;t include a real-time clock (RTC) by default, which meant that it was impossible to
schedule some systemd timers as the time would always jump on boot years ahead on distros like Fedora Server. I got
stuck in a reboot loop with a scheduled reboot job that way, was not fun to recover from.</p>
<p>With the LattePanda IOTA, I have not observed any weird oddities and quirks with it. Even the kernel logs don&rsquo;t show
anything that&rsquo;s problematic, and the RTC is handy to have around as that helps avoid the issue mentioned above.</p>
<h2 id="active-cooler">
  <a class="heading-anchor" href="#active-cooler">Active cooler<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With the LattePanda V1, the cooler was not strictly required, but strongly recommended if you were going to use the
board with moderate to high sustained loads. My solution was to slap an inappropriately sized heat sink to it with a
thermal pad and zip ties and/or velcro strips, which looked horrible, because it was.</p>
<p>With the LattePanda IOTA, the cooler is now a <em><strong>mandatory</strong></em> part of the assembly. It can be fitted with
either
a <a href="https://www.dfrobot.com/product-2988.html">passive cooler</a>, <a href="https://www.dfrobot.com/product-2992.html">a case with passive cooling</a>,
or an <a href="https://www.dfrobot.com/product-2987.html">active cooler</a>.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/active-cooler-0.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/active-cooler-0_hu_c12676e55237e93e.webp"
     width="1000"
     height="537"
     loading="lazy"
     decoding="async"
     alt="LattePanda IOTA next to the active cooler.">

  </a>
  <figcaption class="center">LattePanda IOTA next to the active cooler.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/active-cooler-1.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/active-cooler-1_hu_7ff1b540440bb8f8.webp"
     width="1000"
     height="703"
     loading="lazy"
     decoding="async"
     alt="The bottom of the active cooler.">

  </a>
  <figcaption class="center">The bottom of the active cooler.</figcaption>
</figure>

<p>The active cooler does a good job of keeping the board cool, but it does get super loud at higher loads. The default fan
curve is very primitive, with the fan changing it speeds in big and sudden increments. Bursty workloads certainly <em>feel</em>
bursty with this fan. You will not want to be in the same room with this active cooler.</p>
<p>The sound profile is very similar to a thin and light laptop, and the fan has a <em><strong>very</strong></em> strong high-pitched whine to
it.</p>
<p><a href="/posts/2025/11/18/lattepanda-iota/media/active-cooler.mp3">Here&rsquo;s an audio recording of the noise under heavy load if you&rsquo;re interested (MP3 file). Recorded using a Google Pixel 8a.</a></p>
<p>You can mitigate the active cooler noise issue by reducing the CPU clock speed by setting a lower power limit in UEFI
settings, or on Linux, setting a lower CPU performance ceiling using <code>intel_pstate</code> driver <code>max_perf_pct</code> option once on
boot. This comes at the obvious cost of some raw performance, but given that CPU power scales non-linearly, you may not
even notice it that much.</p>
<p>If you are sensitive to fan noise, then do get the passive cooler and slap a Noctua fan on it, it will likely be a much
better experience with both the cooling performance and noise levels.</p>
<p>Oh, and fun fact: I got so carried away with testing that <strong>I actually forgot to remove the plastic film on the larger
thermal pad</strong> that cools supporting components.</p>
<p><em><strong>And then I did about 24 hours of stress testing with that arrangement.</strong></em></p>
<p>I can confirm that the design of the board is idiot-proof, as I did not actually notice any severe throttling or thermal
issues with that mistake. You can actually see the plastic film being present in a few photos of the board in this
review. I still can&rsquo;t believe that after all these years I ended up making <em><strong>that one mistake</strong></em> that you usually see
online in tech support gore posts.</p>
<h2 id="power-consumption">
  <a class="heading-anchor" href="#power-consumption">Power consumption<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The idle power consumption of the LattePanda IOTA seems to be around 4.0W, which is more than the Raspberry Pi 5 8GB
with its power
consumption <a href="https://www.jeffgeerling.com/blog/2024/new-2gb-pi-5-has-33-smaller-die-30-idle-power-savings">being around 3.2W.</a>
Slightly higher compared to that, but lower than most x86 mini PC-s with idle power consumption typically in the range
of 6-14W.</p>
<p>During the disk read speed stress test, I saw a maximum of 24.4W pulled from the wall.</p>
<p>With the disk read stress test and a full CPU stress test, I saw a peak of 36.3W, with it quickly dropping down as the
CPU settled down at a lower clock speed.</p>
<h2 id="home-server">
  <a class="heading-anchor" href="#home-server">Home server<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This board came surprisingly close to my perfect home server criteria that I had outlined earlier this year.</p>
<p>Less than 5W when idling? Check.</p>
<p>10+ TB of redundant storage? <a href="/posts/2025/10/06/datablocks-white-label-drives/">Check.</a></p>
<p>4 modern cores&rsquo; worth of CPU performance? Check.</p>
<p>Enough performance during bursty workloads? So far, yes.</p>
<p>I then installed a fresh copy of Fedora Server 43 and moved all my home server workloads to it. The eMMC storage is used
as a boot drive, <code>journald</code> writes are disabled, workloads requiring good latency and speed are on the 512GB NVMe SSD,
and bulk storage is connected via two existing USB-SATA adapters taken from one of those WD Elements/MyBook external
hard drive enclosures.</p>
<p>Then it just worked. No issues.<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup></p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/home-server.jpg">
    <img src="/posts/2025/11/18/lattepanda-iota/media/home-server_hu_5194e24434b1f066.webp"
     width="1000"
     height="749"
     loading="lazy"
     decoding="async"
     alt="The LattePanda IOTA next to two 18TB hard drives, running as a home server.">

  </a>
  <figcaption class="center">The LattePanda IOTA next to two 18TB hard drives, running as a home server.</figcaption>
</figure>

<p>The drop in the overall power consumption of my whole home server and networking stack was also immediately noticeable.</p>









<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/power-consumption.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/power-consumption_hu_6fcbbf1adf7484c5.webp"
     width="1000"
     height="656"
     loading="lazy"
     decoding="async"
     alt="Solid 10W drop in normal use.">

  </a>
  <figcaption class="center">Solid 10W drop in normal use.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/cpu.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/cpu_hu_9717d24be3191575.webp"
     width="1000"
     height="657"
     loading="lazy"
     decoding="async"
     alt="CPU usage on the ThinkPad T430 vs the LattePanda IOTA (the gap is the server migration). Same workloads in both.">

  </a>
  <figcaption class="center">CPU usage on the ThinkPad T430 vs the LattePanda IOTA (the gap is the server migration). Same workloads in both.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/memory.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/memory_hu_b7f4eeeb01b4598c.webp"
     width="1000"
     height="657"
     loading="lazy"
     decoding="async"
     alt="Memory consumption, ThinkPad T430 (16GB DDR3) vs LattePanda IOTA (8GB DDR5).">

  </a>
  <figcaption class="center">Memory consumption, ThinkPad T430 (16GB DDR3) vs LattePanda IOTA (8GB DDR5).</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/18/lattepanda-iota/media/temps.png">
    <img src="/posts/2025/11/18/lattepanda-iota/media/temps_hu_a0a2f6525ea35be8.webp"
     width="1000"
     height="442"
     loading="lazy"
     decoding="async"
     alt="Temperature readings, ThinkPad T430 vs LattePanda IOTA with the active cooler.">

  </a>
  <figcaption class="center">Temperature readings, ThinkPad T430 vs LattePanda IOTA with the active cooler.</figcaption>
</figure>

<p>Here are my observations of the CPU performance and behaviour after hitting it with an all-core CPU load:</p>
<ul>
<li>2.9 GHz for a short time period (10-15 seconds), with CPU hovering around 80°C</li>
<li>2.2-2.3 GHz after that, with the CPU dropping to around 70°C</li>
</ul>
<p>I have seen the CPU hit around 3.6 GHz with a single core load while there is nothing running in the background, but
during my normal home server operations the cores are doing enough work across all 4 cores, so that doesn&rsquo;t happen all
that often, and 2.9 GHz is the ceiling for single core performance.</p>
<p>The only limiting factor so far has been the 8 GB of memory on my review unit, but on the bright side that limitation
forced me to review the memory usage of some of the jobs that I run on my home server, which ended up with me finding a
few resource hogs and then fixing them all up. Now I can run about 30 Docker containers of various resource consumption
on a single board computer, and with less than 4GB of RAM used. I set up an 8GB swap file on the SSD, just in case.</p>
<p>Thanks to the relatively small boot drive, I also learned that even if you move the Docker <code>data-root</code> folder to another
location, <code>containerd</code> will still clutter up your boot drive, so you&rsquo;ll have to change that path in
its <code>/etc/containerd/config.toml</code> file <code>root</code> setting.</p>
<p>I&rsquo;m genuinely impressed with how well the LattePanda IOTA runs as a home server. The board isn&rsquo;t really designed with
that use case in mind, and I suspect that the Intel N150 might be doing most of the heavy lifting here, but still, very
impressive!</p>
<p><strong>Is it the perfect home server?</strong> No, but it&rsquo;s pretty damn close to my definition of it.</p>
<h2 id="uefi-settings-tour">
  <a class="heading-anchor" href="#uefi-settings-tour">UEFI settings tour<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>For those interested in what options are available on the board via its UEFI settings, here are some screenshots of the
settings.<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup></p>
<ul>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-0.jpg">Main view</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-1.jpg">Advanced</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-2.jpg">Advanced -&gt; ACPI</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-3.jpg">Advanced -&gt; CPU configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-4.jpg">Advanced -&gt; Super IO configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-5.jpg">Advanced -&gt; Serial port 1 configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-6.jpg">Advanced -&gt; SMART Fan Control</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-7.jpg">Advanced -&gt; Trusted Computing</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-8.jpg">Advanced -&gt; NVMe configuration</a> (no device connected at time of screenshot, oops)</li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-9.jpg">Advanced -&gt; Power configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-10.jpg">Advanced -&gt; USB configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-11.jpg">Advanced -&gt; Serial Port console redirection</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-12.jpg">Advanced -&gt; SDIO configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-13.jpg">Advanced -&gt; Realtek PCIe Ethernet controller</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-14.jpg">Chipset</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-15.jpg">Chipset -&gt; System Agent (SA) configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-16.jpg">Chipset -&gt; Device configuration</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-17.jpg">Security</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-18.jpg">Security -&gt; Secure Boot</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-19.jpg">Boot</a></li>
<li><a href="/posts/2025/11/18/lattepanda-iota/media/uefi-20.jpg">Save &amp; Exit</a></li>
</ul>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If the LattePanda IOTA with its adapters fits your project requirements, you&rsquo;re aware of its limitations, and the
price is right, then I believe it&rsquo;s a solid choice for your next project. My testing didn&rsquo;t immediately break it, even
when I forgot to remove the plastic film on one of the thermal pads.</p>
<p>The current pricing of it and its accessories seem to be roughly in the ballpark of the Raspberry Pi 5 8GB (based on
prices in Estonia). Boards like <a href="https://shop.zimaspace.com/products/zimaboard2-single-board-server">the Zimaboard 2</a>
<strong><em>(have not tested it myself)</em></strong> are more expensive, but they&rsquo;re also catering to a slightly different audience and
have better specs, like 2.5G Ethernet ports and SATA ports with power delivery suitable for running two 3.5&quot; hard drives
straight from the board.</p>
<p>It&rsquo;s hard to beat the bargain that you can get from a used mini PC or NAS, but it won&rsquo;t come with the charm, low power
consumption and bragging rights that a single board computer gets you, especially if you&rsquo;re using it for an off-label
use case like I am.<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup></p>
<p>In the meantime, I&rsquo;ll keep rocking it as a home server. In case something noteworthy happens, I&rsquo;ll update this post,
which is brought to you by the very same LattePanda IOTA at the time of publishing.</p>
<h2 id="2025-12-12-update">
  <a class="heading-anchor" href="#2025-12-12-update">2025-12-12 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>About a month after switching my home server workloads to it, the LattePanda IOTA is still rock solid. No issues with
USB HDD stability as well.</p>
<p>The only complaint that carries over from the review is the fact that the active cooler is still way too loud. I&rsquo;m
seriously considering getting the passive cooler for it to shut it up. I can hear it from the bedroom while the IOTA is
in a closet on the other side of the apartment!</p>
<p>I also played around with Intel RAPL settings, which allow you to control the power budget of the CPU on the fly.</p>
<p>The power limit is 10W by default, and short term power limit is 20W. You can control it via these toggles:</p>
<pre tabindex="0"><code>/sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw
/sys/class/powercap/intel-rapl/intel-rapl:0/constraint_1_power_limit_uw
</code></pre><p>Get current values:</p>
<pre tabindex="0"><code>cat /sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw
cat /sys/class/powercap/intel-rapl/intel-rapl:0/constraint_1_power_limit_uw
</code></pre><p>Set a new limit of 8W to both:</p>
<pre tabindex="0"><code>echo 8000000 &gt; /sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw
echo 8000000 &gt; /sys/class/powercap/intel-rapl/intel-rapl:0/constraint_1_power_limit_uw
</code></pre><p>These reset every boot, so you should probably set a one-shot systemd unit to call these early in the boot cycle.</p>
<p>The LattePanda IOTA is the most exciting yet boring addition to my setup. It just works.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>this also marks the first time that I&rsquo;ve been sent a review sample throughout the course of running this blog!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>do note that with most M.2 PCIe-&gt;SATA adapters, the controller of the adapter determines how good of an experience
you will have. With some, I&rsquo;ve read that the controllers may not handle some failure scenarios well, one device having
issues may throw off the whole controller, and now you have a bigger mess.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>the earliest PC motherboard with a gigabit Ethernet connection that I&rsquo;ve personally used was manufactured in 2006.
That&rsquo;s how long gigabit Ethernet has been around for in the consumer space.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>say that 10 times in a row!&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>I know, that usually does not happen on this blog.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>being <a href="/posts/2025/02/17/influencer/">a prolific open source influencer</a> does not bring in as much money as you&rsquo;d
think, so I haven&rsquo;t bought a proper capture device yet.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>no, but seriously, I cannot be the only one who has a strange affection towards SBC-s with their bare PCB-s.
I can&rsquo;t tell a capacitor from a resistor, but the boards are just so damn cool, right?&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>The day IPv6 went away</title><link>https://ounapuu.ee/posts/2025/11/06/ipv6-is-kill/</link><pubDate>Thu, 06 Nov 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/11/06/ipv6-is-kill/</guid><description>Well, that's a first.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/11/06/ipv6-is-kill/media/cover_hu_464d143a945f4e35.jpg" width="1200" height="630" alt="The day IPv6 went away" /><p>I take pride in <a href="/posts/2024/06/24/back-to-roots/">hosting my blog on a 13-year old ThinkPad acting as a home server</a>,
but sometimes it&rsquo;s kind of a pain. It&rsquo;s only fair that I cover the downsides of this setup in contrast to all the
positives.</p>
<p>Yesterday, I happened to notice that a connection to a backup endpoint was gone. Okay, happens sometimes. Then I went
into the router and noticed that hey, that&rsquo;s odd, there&rsquo;s no WAN6 connection showing up. All gone. Just as if I had gone
back to a crappy ISP that only provides IPv4<a href="https://www.elisa.ee/">!</a></p>
<p>Restarting the interface did not work, but a full router restart worked.</p>
<p>Since the IPv4 address and IPv6 prefix are all dynamic, that meant that my DNS entries had just gone stale. I do
have a custom DNS auto-updater script for my DNS provider, but DNS propagation takes time. Luckily not a lot of time, my
uptime checker only reported downtime of 5-15 minutes, depending on the domain.</p>
<p>Here&rsquo;s what it looked like on OpenWRT.</p>









<figure class="center">
  <a href="/posts/2025/11/06/ipv6-is-kill/media/openwrt.png">
    <img src="/posts/2025/11/06/ipv6-is-kill/media/openwrt_hu_cc5a6092998c51ea.webp"
     width="1000"
     height="257"
     loading="lazy"
     decoding="async"
     alt="The IPv4 only experience.">

  </a>
  <figcaption class="center">The IPv4 only experience.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/06/ipv6-is-kill/media/interfaces.png">
    <img src="/posts/2025/11/06/ipv6-is-kill/media/interfaces_hu_a95c298721c380e6.webp"
     width="1000"
     height="631"
     loading="lazy"
     decoding="async"
     alt="Interface was still there, just not in a happy state.">

  </a>
  <figcaption class="center">Interface was still there, just not in a happy state.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/06/ipv6-is-kill/media/cli.png">
    <img src="/posts/2025/11/06/ipv6-is-kill/media/cli_hu_9754341e943c5a3d.webp"
     width="344"
     height="356"
     loading="lazy"
     decoding="async"
     alt="Interface down, in pending state.">

  </a>
  <figcaption class="center">Interface down, in pending state.</figcaption>
</figure>

<p>Impact to my blog? Not really noticeable, since IPv4 kept trucking along. Perhaps a few IPv6-only readers may have
noticed this.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>I can always move to a cheap VPS or <em><strong>the cloud</strong></em> at a moments&rsquo; notice, but where&rsquo;s the fun in that? I can
produce <a href="https://aws.amazon.com/message/101925/">AWS levels of uptime</a> at home, <em>thankyouverymuch</em>!</p>
<p>I think I&rsquo;ll now need to figure out some safeguards, even if it means scheduling a weekly router reboot if the WAN6
interface is not up for X amount of time.</p>
<p>That, and better monitoring.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>if you are that person, say hi!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Why Nextcloud feels slow to use</title><link>https://ounapuu.ee/posts/2025/11/03/nextcloud-slow/</link><pubDate>Mon, 03 Nov 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/11/03/nextcloud-slow/</guid><description>No amount of tuning the backend service performance helped, and then I learned why. Oh no. Oh no no no no.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/11/03/nextcloud-slow/media/cover_hu_209d18adff113b2d.jpg" width="1200" height="630" alt="Why Nextcloud feels slow to use" /><p><a href="https://nextcloud.com/">Nextcloud.</a> I really want to like it, but it&rsquo;s making it really difficult.</p>
<p>I like what Nextcloud offers with its feature set and how easily it replaces a bunch of services under one roof (files,
calendar, contacts, notes, to-do lists, photos etc.), but no matter how hard I try and how much I optimize its resources
on my home server, it feels slow to use, even on hardware that is ranging from decent to good. Then I opened developer
tools and found the culprit.</p>
<p><em><strong>It&rsquo;s the Javascript.</strong></em></p>
<p>On a clean page load, you will be downloading about <strong>15-20 MB</strong> of Javascript, which does compress down to about 4-5
MB in transit, but that is still <strong>a huge amount of Javascript.</strong> For context, I consider 1 MB of Javascript to be on the
heavy side for a web page/app.</p>
<p>Yes, that Javascript will be cached in the browser for a while, but you will still be executing all of that on each
visit to your Nextcloud instance, and that will take a long time due to the sheer amount of code your browser now has to
execute on the page.</p>
<p>A significant contributor to this heft seems to be the <code>core-common.js</code> bundle, which based on its name seems to provide
some common functionality that&rsquo;s shared across different Nextcloud apps that one can install. It&rsquo;s coming in at <strong>4.71
MB</strong> at the time of writing.</p>
<p>Then you want notifications, right? <code>NotificationsApp.chunk.mjs</code> is here to cover you, at <strong>1.06 MB</strong>.</p>
<p>Then there are the app-specific views. The Calendar app is taking up <strong>5.94 MB</strong> to show a basic calendar view.</p>









<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/calendar.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/calendar_hu_fc4a2bcf700ca3e9.webp"
     width="814"
     height="676"
     loading="lazy"
     decoding="async"
     alt="Nextcloud Calendar app Javascript assets.">

  </a>
  <figcaption class="center">Nextcloud Calendar app Javascript assets.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/calendar-view.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/calendar-view_hu_c5b3f9ee8e0c3e6e.webp"
     width="1000"
     height="547"
     loading="lazy"
     decoding="async"
     alt="This is what 14 MB of Javascript gets you, after about 30 seconds of loading on a poor connection.">

  </a>
  <figcaption class="center">This is what 14 MB of Javascript gets you, after about 30 seconds of loading on a poor connection.</figcaption>
</figure>

<p>Files app includes a bunch of individual scripts, such as <code>EditorOutline</code> (<strong>1.77 MB</strong>), <code>previewUtils</code> (<strong>1.17 MB</strong>),
<code>index</code> (<strong>1.09 MB</strong>), <code>emoji-picker</code> (<strong>0.9 MB</strong> which I&rsquo;ve never used!) and many smaller ones.</p>









<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/files.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/files_hu_e18f40417adc506e.webp"
     width="825"
     height="914"
     loading="lazy"
     decoding="async"
     alt="Nextcloud Files app Javascript assets.">

  </a>
  <figcaption class="center">Nextcloud Files app Javascript assets.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/files-view.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/files-view_hu_4ca5b36750b415c9.webp"
     width="1000"
     height="547"
     loading="lazy"
     decoding="async"
     alt="This is what 18.8 MB of Javascript gets you. I waited for a whole minute for it to load in a real world poor internet
connectivity scenario.">

  </a>
  <figcaption class="center">This is what 18.8 MB of Javascript gets you. I waited for a whole minute for it to load in a real world poor internet
connectivity scenario.</figcaption>
</figure>

<p>Notes app with its basic bare-bones editor? <strong>4.36 MB</strong> for the <code>notes-main.js</code>!</p>









<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/notes.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/notes_hu_35336dfe028da897.webp"
     width="821"
     height="955"
     loading="lazy"
     decoding="async"
     alt="Nextcloud Notes app Javascript assets. This isn&#39;t even half of it!">

  </a>
  <figcaption class="center">Nextcloud Notes app Javascript assets. This isn&#39;t even half of it!</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/11/03/nextcloud-slow/media/notes-view.png">
    <img src="/posts/2025/11/03/nextcloud-slow/media/notes-view_hu_ef8ac2cdbc3ee6d3.webp"
     width="1000"
     height="547"
     loading="lazy"
     decoding="async"
     alt="20.91 MB of Javascript, for this?">

  </a>
  <figcaption class="center">20.91 MB of Javascript, for this?</figcaption>
</figure>

<p>This means that even on an iPhone 13 mini, opening the Tasks app (to-do list), will take a ridiculously long time.
Imagine opening your shopping list at the store and having to wait 5-10 seconds before you see anything, even with a
solid 5G connection. Sounds extremely annoying, right?</p>
<p>I suspect that a lot of this is due to how Nextcloud is architected. There&rsquo;s bound to be some hefty common libraries and
tools that allow app developers to provide a unified experience, but even then there is something seriously wrong with
the end result, the functionality to bundle size ratio is way off.</p>
<p>As a result, I&rsquo;ve started branching out some things from Nextcloud, such as replacing the Tasks app with using a
private <a href="https://vikunja.io/">Vikunja</a> instance, and Photos to a private <a href="https://immich.app/">Immich</a> instance. Vikunja
is not perfect, but its 1.5 MB of Javascript is an order of magnitude smaller compared to Nextcloud, making it feel
incredibly fast in comparison.</p>
<p>However, with other functionality I have to admit that the convenience of Nextcloud is enough to dissuade me from
replacing it elsewhere, due to the available feature set comparing well to alternatives.</p>
<p><em><strong>For now.</strong></em></p>
<p>I&rsquo;m sure that there are some legitimate reasons behind the current state, and overworked development teams and
volunteers are unfortunately the norm in the industry, but it doesn&rsquo;t take away the fact that the user experience and
accessibility suffers as a result.</p>
<p>I&rsquo;d like to thank <a href="https://infrequently.org/about-me/">Alex Russell</a> for writing about web performance and why it
matters, with supporting evidence and actionable advice, it has changed how I view websites and web apps and has pushed
me to be better in my own work. I highly suggest reading his content, starting
with <a href="https://infrequently.org/series/performance-inequality/">the performance inequality gap series.</a> It&rsquo;s educational,
insightful and incredibly irritating once you learn how crap most things are and how careless a lot of development teams
are towards performance and accessibility.</p>
]]></content:encoded></item><item><title>Testing two 18 TB white label SATA hard drives from datablocks.dev</title><link>https://ounapuu.ee/posts/2025/10/06/datablocks-white-label-drives/</link><pubDate>Mon, 06 Oct 2025 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/10/06/datablocks-white-label-drives/</guid><description>It has been 0 days since the last change to my home server.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/10/06/datablocks-white-label-drives/media/cover_hu_62398be5795c9b74.jpg" width="1200" height="630" alt="Testing two 18 TB white label SATA hard drives from datablocks.dev" /><p>This post is <em><strong>NOT</strong></em> sponsored, the products were bought with my hard-earned money.</p>
<p>I&rsquo;ve been running a full SSD storage setup for a few years in my home server and I&rsquo;ve been happy with it, except for the
storage anxiety that I get with running small pools of fast storage, which is why I started looking at how the hard
drive market is doing.</p>
<p>Half of tech YouTube has been sponsored by companies like ServerPartDeals, so they were one of the first
places I looked at, but they seem to only operate within the US and the shipping+taxes destroy any price advantages from
ordering there to Estonia (which is in Europe).</p>
<p>At some point I stumbled upon <a href="https://datablocks.dev/">datablocks.dev</a>, which seems to operate within a similar niche,
but in Europe and on a much smaller scale. What caught my eye were their white label hard drive offerings. Their website
has a good explanation on
the <a href="https://datablocks.dev/blogs/news/white-label-vs-recertified-drives">differences between recertified and white label hard drives.</a>
In short: white label drives have no branding, have no or very low number of power-on hours, may have small scratches or
dents, but are in all other aspects completely functional and usable.</p>
<p>White label drives also have a price advantage compared to branded recertified drives. Here&rsquo;s one example with 18 TB
drives, the recertified one is 16.7% more expensive compared to the white label one, and the only obvious difference
seems to be the sticker on the drive. I highly suspect that the white label one is also manufactured by Seagate based on
the physical similarities.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/pricing.png">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/pricing_hu_557f72882995374.webp"
     width="711"
     height="673"
     loading="lazy"
     decoding="async"
     alt="The price difference between a recertified and a white label drive.">

  </a>
  <figcaption class="center">The price difference between a recertified and a white label drive.</figcaption>
</figure>

<p>I took some time to think things over and compared the pricing of various drives. The drives were all competitively
priced between each other, with the price per terabyte hovering around 13 EUR/TB, so it didn&rsquo;t matter much which drive
size you picked, you&rsquo;d still get a pretty solid deal. It was also a better deal compared to using an WD Elements/My Book
drive of the same size.</p>
<p>I decided to go with two 18 TB hard drives. I considered buying the 20 TB or 22 TB capacities, but decided to go with 18
TB because it&rsquo;s the largest single hard drive that I can easily and quickly buy a replacement for in the form of a WD
Elements/My Book drive.</p>
<p>The stock on <code>datablocks.dev</code> is quite volatile, the drives are in stock when new batches arrive, but they can also
quickly go out of stock. I saw this live with the 22 TB hard drives, one day there are 35 left, the next day there can
be 7 left, and then only one lone drive.</p>
<p>At the time of writing, the 18 TB model that I bought is out of stock, so my choice to go with a slightly smaller but
more easily replaceable one is validated.</p>
<p>For those that have followed my blog for a while will know that I&rsquo;m a huge fan of all-SSD server
builds, <a href="https://www.jeffgeerling.com/blog/2024/radxas-sata-hat-makes-compact-pi-5-nas">especially this one by Jeff Geerling that I still consider building from time to time.</a>
If I dislike noise, higher power usage and slower performance, then why did I get the hard drives? It&rsquo;s simple, really:
I now have an actual closet that I can stash my home server in, meaning that noise isn&rsquo;t that big of a worry, and as
long as my home server takes about the same amount of power as my refrigerator or dishwasher, then that&rsquo;s fine.
SSD prices still haven&rsquo;t gone down as much as I&rsquo;ve hoped over the years, so the all-SSD build ideas that I have are way
outside my budget.</p>
<p>The drives arrived in a reasonable time window. The packaging was adequate, although I was slightly concerned with the
cardboard box showing signs of something hitting it hard. The drives were packaged within sealed antistatic bags, and
with ample bubble wrap surrounding them.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-1.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-1_hu_a9dba89172bc3c4.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="The cardboard box with a slight dent.">

  </a>
  <figcaption class="center">The cardboard box with a slight dent.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-2.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-2_hu_7dbb3525f71376b8.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Plenty of paper inside to prevent the drives from flying around.">

  </a>
  <figcaption class="center">Plenty of paper inside to prevent the drives from flying around.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-3.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-3_hu_391e44195be9b89b.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Drives were wrapped in bubble wrap, with the drives themselves also separated with a few layers of it for maximum
protection.">

  </a>
  <figcaption class="center">Drives were wrapped in bubble wrap, with the drives themselves also separated with a few layers of it for maximum
protection.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-4.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/packaging-4_hu_2f0b8482d4f6a778.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Drives in anti-static bags.">

  </a>
  <figcaption class="center">Drives in anti-static bags.</figcaption>
</figure>

<p>Just as described, the drives did have slight scratches and very minor dents in them, but in all other aspects they
looked like new.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drive-0.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drive-0_hu_d83039e15059e17b.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="One of the hard drives. It does have slight dents and scratches, matching the description.">

  </a>
  <figcaption class="center">One of the hard drives. It does have slight dents and scratches, matching the description.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drive-1.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drive-1_hu_ae9c6c9ec935f236.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="The second drive had a more noticeable bump in it.">

  </a>
  <figcaption class="center">The second drive had a more noticeable bump in it.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drive-backside.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drive-backside_hu_31c6dbfeabd631da.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="The backside of the drives.">

  </a>
  <figcaption class="center">The backside of the drives.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drive-wd-adapter.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drive-wd-adapter_hu_12335c95ee248c0e.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Those USB-SATA adapters from shucking are really darn handy now. Adapter courtesy of my brother-in-law.">

  </a>
  <figcaption class="center">Those USB-SATA adapters from shucking are really darn handy now. Adapter courtesy of my brother-in-law.</figcaption>
</figure>

<p>Before putting them to use, I formatted the drives using <code>badblocks</code>. It took a full 24 hours to do a full drive write.
The write performance peaked at 275 MB/s and slowed down to 123 MB/s at the end, which is expected.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/performance.png">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/performance_hu_9faa269c4173536c.webp"
     width="1000"
     height="300"
     loading="lazy"
     decoding="async"
     alt="The performance of the drive during the full drive format.">

  </a>
  <figcaption class="center">The performance of the drive during the full drive format.</figcaption>
</figure>

<p>I also had to choose a larger block size for <code>badblocks</code> because otherwise it could not handle the drive, resulting in
the command
being <code>badblocks -wsv -b 8192 /dev/sdX</code>.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/peak-performance.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/peak-performance_hu_ce21ef2456c6c9b3.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="This is what peak jank looks like.">

  </a>
  <figcaption class="center">This is what peak jank looks like.</figcaption>
</figure>

<p>I unfortunately did not save the SMART data from the time I received the drives, but the contents were as expected,
there were no more than a few power on hours and other metrics were OK. Keep in mind that it&rsquo;s also possible to reset
SMART data on a drive so this information cannot be taken at face value.</p>
<p>The drives are noisy, as expected. They run at 7200 RPM and do the usual clicks and clacks that a normal hard drive
does. If this bothers you, <a href="/posts/2021/04/02/tech-tip-1/">use foam to fix it.</a> The soft side of a sponge can work
just as well.</p>
<p>With these drives <a href="/posts/2023/03/26/tiered-storage/">I&rsquo;ve now followed my own advice</a> and tiered my storage: two 1 TB
SSD-s for the things that benefit from good speed and latency (databases, containers), and 18 TB hard drives for
bulk storage, backups and less frequently used data. Coming from an all-SSD build, I expected the performance to drop in
day-to-day operations, but in most cases I cannot tell a difference. My family photos load just fine, media plays back
well, and backups take slightly longer, which isn&rsquo;t noticeable due to them running during the night. Only when I look at
the Prometheus node exporter graphs do I notice that sometimes the server is waiting behind the disks a bit more due to
higher <code>iowait</code>.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/iowait.png">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/iowait_hu_62d2f4a247e6e5b1.webp"
     width="1000"
     height="452"
     loading="lazy"
     decoding="async"
     alt="During full backups or disk scrubs, the iowait is more prevalent on graphs (the red part), but that doesn&#39;t seem to
impact my other workloads in a significant way.">

  </a>
  <figcaption class="center">During full backups or disk scrubs, the iowait is more prevalent on graphs (the red part), but that doesn&#39;t seem to
impact my other workloads in a significant way.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drives-in-use-0.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drives-in-use-0_hu_734ffb597eff0fec.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="The drives are connected via two WD Elements/My Book USB-SATA adapters, over USB 3.0, and stored right below my ThinkPad
T430, which is proudly running as my home server.">

  </a>
  <figcaption class="center">The drives are connected via two WD Elements/My Book USB-SATA adapters, over USB 3.0, and stored right below my ThinkPad
T430, which is proudly running as my home server.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/drives-in-use-1.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/drives-in-use-1_hu_ed0078e342cbd321.webp"
     width="751"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="I added glue-on rubber feet on the stand to make sure the drives do not accidentally slip off anywhere. It does nothing
to reduce the noise, though, and I&#39;m convinced that it&#39;s actually making the noise worse.">

  </a>
  <figcaption class="center">I added glue-on rubber feet on the stand to make sure the drives do not accidentally slip off anywhere. It does nothing
to reduce the noise, though, and I&#39;m convinced that it&#39;s actually making the noise worse.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/home-server.jpg">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/home-server_hu_116154110711149.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="I&#39;m not proud of the lack of cable management, but this setup works well. Given how often I get new ideas, it doesn&#39;t
make sense to organize this too much anyway.">

  </a>
  <figcaption class="center">I&#39;m not proud of the lack of cable management, but this setup works well. Given how often I get new ideas, it doesn&#39;t
make sense to organize this too much anyway.</figcaption>
</figure>

<p>The power usage did shoot up as a result, roughly 10-20 W. Not ideal, but my whole networking and home server setup is
idling at below 45 W, and I&rsquo;ve
had <a href="/posts/2021/03/17/server-setups-throughout-the-years/">less efficient home servers in the past,</a> so it&rsquo;s not that
big of a deal.</p>









<figure class="center">
  <a href="/posts/2025/10/06/datablocks-white-label-drives/media/setup-power-usage.png">
    <img src="/posts/2025/10/06/datablocks-white-label-drives/media/setup-power-usage_hu_39a1f182a81cdbb4.webp"
     width="1000"
     height="601"
     loading="lazy"
     decoding="async"
     alt="The power usage was elevated while I was formatting and copying files over to the new drives, but after that it&#39;s
stabilized to around 1.2 kWh per day.">

  </a>
  <figcaption class="center">The power usage was elevated while I was formatting and copying files over to the new drives, but after that it&#39;s
stabilized to around 1.2 kWh per day.</figcaption>
</figure>

<p>In this configuration, the drives run quite cool. During formatting on a hot day, I saw them go up to a maximum of 51°C,
but in general use they sit at around 38-42°C.</p>
<p>Overall, I&rsquo;m reasonably happy with the drives. I expect these to last me at least 5 years, and I&rsquo;m probably going to
switch one of the drives out a bit sooner to reduce the risk of a full drive pool failure. They&rsquo;ve made it the first 50
days, so that&rsquo;s good!</p>
<p>Oh, and here&rsquo;s the <code>smartctl -ax</code> output for the disks after running them for about two months:</p>
<ul>
<li><a href="/posts/2025/10/06/datablocks-white-label-drives/media/disk1.txt">disk 1</a></li>
<li><a href="/posts/2025/10/06/datablocks-white-label-drives/media/disk2.txt">disk 2</a></li>
</ul>
<h2 id="2026-02-13-update">
  <a class="heading-anchor" href="#2026-02-13-update">2026-02-13 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>6 months later, and my drives are still doing well. <code>smartctl -ax</code> output:</p>
<ul>
<li><a href="/posts/2025/10/06/datablocks-white-label-drives/media/disk1-2026-02-13.txt">disk 1</a></li>
<li><a href="/posts/2025/10/06/datablocks-white-label-drives/media/disk2-2026-02-13.txt">disk 2</a></li>
</ul>
<p>In the meantime, what <em>did</em> die on me was a Seagate Portable 4TB drive that I used mainly for backups. :)</p>
<p>A Latvian blogger that I follow also had a pleasant experience with datablocks.dev,
and <a href="https://blog.kronis.dev/blog/buying-some-drives-from-datablocks">they wrote about it here.</a></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>hard drives are expected to be slower at the end of the drive because of their design, the platter rotates at 7200
RPM
but the end of the drive is located at the inner tracks of the platter, near the center of the spindle, which results in
a slower effective speed. Math is cool!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How to run Uptime Kuma in Docker in an IPv6-only environment</title><link>https://ounapuu.ee/posts/2025/08/05/uptime-kuma-ipv6/</link><pubDate>Tue, 05 Aug 2025 21:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/08/05/uptime-kuma-ipv6/</guid><description>When you're too cheap to pay for an IPv4 address but you'd really like to monitor your services.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/08/05/uptime-kuma-ipv6/media/cover_hu_25de9680b02fc40f.jpg" width="1200" height="630" alt="How to run Uptime Kuma in Docker in an IPv6-only environment" /><p>I use <a href="https://github.com/louislam/uptime-kuma">Uptime Kuma</a> to check the availability of a few services that I run,
with the most important one being my blog. It&rsquo;s really nice.</p>
<p>Today I wanted to set it up on a different machine to help troubleshoot and confirm some latency issues that I&rsquo;ve
observed, and for that purpose I picked the cheapest ARM-based Hetzner Cloud VM hosted in Helsinki, Finland.</p>
<p>Hetzner provides a public IPv6 address for free, but you have to pay extra for an IPv4 address. I didn&rsquo;t want to do that
out of
principle, so I went ahead and copied my Docker Compose definition over to the new server.</p>
<p>For some reason, Uptime Kuma would start up on the new IPv6-only VM, but it was unsuccessful in making requests to my
services, which support both IPv4 and IPv6. The requests would time out and show up as &ldquo;Pending&rdquo; in the UI, and the
service logs complained about not being able to deliver e-mails about the failures.</p>
<p>I confirmed IPv6 connectivity within the container by running <code>docker exec -it uptime-kuma bash</code> and running a
few <code>curl</code> and <code>ping</code> commands with IPv6 flags, had no issues with those.</p>
<p>When I added a public IPv4 address to the container, everything started working again.</p>
<p>I fixed the issue by explicitly disabling the IPv4 network in the Docker Compose service definition, and that did the
trick, Uptime Kuma made successful requests towards my services. It seems that the service defaults to IPv4 due to the
internal Docker network giving it an IPv4 network to work with, and that causes issues when your machine doesn&rsquo;t have
any IPv4 network or public IPv4 address associated with it.</p>
<p>Here&rsquo;s an example Docker Compose file:</p>
<pre tabindex="0"><code>name: uptime-kuma
services:
  uptime-kuma:
    container_name: uptime-kuma
    networks:
      - uptime-kuma
    ports:
      - 3001:3001
    volumes:
      - /path/to/your/storage:/app/data
    image: docker.io/louislam/uptime-kuma
    restart: always
networks:
  uptime-kuma:
    enable_ipv6: true
    enable_ipv4: false
</code></pre><p>That&rsquo;s it!</p>
<p>If you&rsquo;re interested in different ways to set up IPv6 networking in
Docker, <a href="/posts/2024/12/20/docker-ipv6/">check out this overview that I wrote a while ago.</a></p>
]]></content:encoded></item><item><title>Lenovo ThinkCentre M900 Tiny: how does it fare as a home server?</title><link>https://ounapuu.ee/posts/2025/06/06/thinkcentre-m900-tiny/</link><pubDate>Fri, 06 Jun 2025 11:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/06/06/thinkcentre-m900-tiny/</guid><description>I was itching for a new project, so I got one.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/06/06/thinkcentre-m900-tiny/media/cover_hu_32af048ce8cd1fbc.jpg" width="1200" height="630" alt="Lenovo ThinkCentre M900 Tiny: how does it fare as a home server?" /><p>My evenings of absent-minded local auction site scrolling<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> paid off: I now own
a <a href="https://www.lenovo.com/gb/en/p/desktops/thinkcentre/m-series-tiny/m900-tiny/11tc1mtm900">Lenovo ThinkCentre M900 Tiny.</a></p>
<p>It&rsquo;s relatively old, being manufactured in 2016<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, but it&rsquo;s tiny and has a lot of useful life left in it.</p>
<p><a href="https://www.servethehome.com/lenovo-thinkcentre-m900-tiny-project-tinyminimicro-guide/">It&rsquo;s also featured in the TinyMiniMicro series by ServeTheHome.</a></p>
<p>I managed to get it for 60 EUR plus about 4 EUR shipping, and it comes with solid specifications:</p>
<ul>
<li>CPU: Intel i5-6500T</li>
<li>RAM: 16GB DDR4</li>
<li>Storage: 256GB SSD</li>
<li>Power adapter included</li>
</ul>
<p>The price is good compared to similar auctions, but was it worth it?</p>
<p>Yes, yes it was.</p>
<p>I have been running <a href="/posts/2024/10/16/third-times-the-charm/">a ThinkPad T430 as a server for a while now,</a> since
October 2024. It served me well in that role and would&rsquo;ve served me for even longer if I wanted to, but I had an itch
for a project that didn&rsquo;t involve renovating an apartment.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/testing-setup.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/testing-setup_hu_ce25c7c29fee65a9.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="When you are in the middle of renovating your living room, but you really want to get on with the server migration.">

  </a>
  <figcaption class="center">When you are in the middle of renovating your living room, but you really want to get on with the server migration.</figcaption>
</figure>

<h2 id="power-usage">
  <a class="heading-anchor" href="#power-usage">Power usage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>One of my main curiosities was around the power usage. Will this machine beat the laptop in terms of efficiency while
idling and running normal home server workloads? Yes, yes it does.</p>
<p>While booting into Windows 11 and calming down a bit, the lowest idle power numbers I saw were around 8 W. This
concludes the testing on Windows.</p>
<p>On Linux (Fedora Server 42), the idle power usage was around 6.5 W to 7 W. After running <code>powertop --auto-tune</code>, I ended
up getting that down to 6.1 W - 6.5 W. This is much lower compared to the numbers that ServeTheHome got, which were
around 11-13 W (120V circuit). My measurements are made in Europe, Estonia, where we have 240V circuits.</p>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/idle-power-linux.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/idle-power-linux_hu_b096580227905f71.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Idle power from the wall on a clean Fedora Server 42 installation (fully headless).">

  </a>
  <figcaption class="center">Idle power from the wall on a clean Fedora Server 42 installation (fully headless).</figcaption>
</figure>

<p>You may be able to find machines where the power usage is even
lower. <a href="https://louwrentius.com/the-raspberry-pi-5-is-no-match-for-a-tini-mini-micro-pc.html">Louwrentius mada an idle power comparison on an HP EliteDesk Mini G3 800</a>
where they measured it at 4 W. That might also be due to other factors in play, or differences in measurement tooling.</p>
<p>During normal home server operation with 5 SATA SSD-s connected (4 of them with USB-SATA adapters), I have observed
power consumption being around 11-15 W, with peaks around 40 W.
On a pure CPU load with <code>stress -c 8</code>, I saw power consumption being around 32 W. Formatting the internal SATA SSD added
5 W to that figure.</p>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/power-usage.png">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/power-usage_hu_638aa8d89c25cfaf.webp"
     width="957"
     height="877"
     loading="lazy"
     decoding="async"
     alt="Daily power consumption of my whole home server infrastructure after installing the new server.">

  </a>
  <figcaption class="center">Daily power consumption of my whole home server infrastructure after installing the new server.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/power-usage-active.png">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/power-usage-active_hu_55918f1fb48345fe.webp"
     width="957"
     height="877"
     loading="lazy"
     decoding="async"
     alt="More accurate power usage numbers over 14 days.">

  </a>
  <figcaption class="center">More accurate power usage numbers over 14 days.</figcaption>
</figure>

<h2 id="usb-storage-are-you-crazy">
  <a class="heading-anchor" href="#usb-storage-are-you-crazy">USB storage, are you crazy?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Yes. But hear me out.</p>
<p>Back in 2021, <a href="/posts/2021/02/08/things-learned-while-self-hosting/">I wrote about USB storage being a very bad idea,</a>
especially on <a href="https://btrfs.readthedocs.io/en/latest/index.html">BTRFS.</a></p>
<p>I&rsquo;ve learned a lot over the years, and BTRFS has received continuous improvements as well.
In <a href="/posts/2024/10/16/third-times-the-charm/">my ThinkPad T430 home server setup,</a> I had two USB-connected SSD-s running
in <em><strong>RAID0</strong></em> for over half a year, and it was completely fine unless you accidentally bumped into the SSD-s.</p>
<p>USB-connected storage <a href="https://knowyourmeme.com/memes/this-is-fine">is fine</a> under the right circumstances:</p>
<ul>
<li>the cables are not damaged</li>
<li>the cables are not at a weird angle or twisted
<ul>
<li>I actually had issues with this point, my very cool and nice cable management resulted in one disk having
connectivity issues, which I fixed by relieving stress on the cables and routing them differently</li>
</ul>
</li>
<li>the connected PC does not have chronic overheating issues</li>
<li>the whole setup is out of the reach of cats, dogs, children and
clumsy <a href="https://www.jeffgeerling.com/blog/2022/cosplaying-sysadmin">sysadmin cosplayers</a></li>
<li>the USB-SATA adapters pass through the device ID and S.M.A.R.T information to the host
<ul>
<li>the device ID part especially is key to avoiding issues with various filesystems (especially ZFS) and storage pool
setups</li>
<li><a href="https://icybox.de/product/externe_speicherloesungen/IB-223U3a-B">the ICY BOX IB-223U3a-B is a good option that I have personally been very happy with</a>,
and it&rsquo;s what I&rsquo;m using in this server build</li>
<li>a lot of adapters (mine included) don&rsquo;t support running SSD TRIM commands to the drives, which might be a concern
<ul>
<li>has not been an issue for over half a year with those ICY BOX adapters, but it&rsquo;s something to keep in mind</li>
</ul>
</li>
</ul>
</li>
<li>you are not using an SBC as the home server
<ul>
<li>even a Raspberry Pi 4 can barely handle one USB-powered SSD
<ul>
<li>not an issue if you use an externally powered drive, or an USB DAS</li>
</ul>
</li>
</ul>
</li>
</ul>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-0.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-0_hu_e535336c8ddf5c4a.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="The initial version of the new setup.">

  </a>
  <figcaption class="center">The initial version of the new setup.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-1.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-1_hu_cc106245ab989434.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="I liked how the drives fit on top of the PC here.">

  </a>
  <figcaption class="center">I liked how the drives fit on top of the PC here.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-2.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-2_hu_731027e3582a97e6.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Another angle on the new setup.">

  </a>
  <figcaption class="center">Another angle on the new setup.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-3.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v1-3_hu_49bebb6bec9f0435.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Unfortunately, this mess of cables did not work out at all, with one drive being unstable.">

  </a>
  <figcaption class="center">Unfortunately, this mess of cables did not work out at all, with one drive being unstable.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v2-0.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v2-0_hu_6685bd5f66709a2e.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="Second version of the setup. This one works very well.">

  </a>
  <figcaption class="center">Second version of the setup. This one works very well.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v2-1.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/server-setup-v2-1_hu_4c0691d4a55c87f0.webp"
     width="1000"
     height="751"
     loading="lazy"
     decoding="async"
     alt="The cables are not that neatly organized, but there is much less stress on the connectors, ensuring a more stable
connection.">

  </a>
  <figcaption class="center">The cables are not that neatly organized, but there is much less stress on the connectors, ensuring a more stable
connection.</figcaption>
</figure>

<p>After a full BTRFS scrub and a few days of running, it seems fine. Plus it looks sick as hell with the identical drives
stacked on top. All that&rsquo;s missing are labels specifying which drive is which, but I&rsquo;m sure that I&rsquo;ll get to that
someday, hopefully before a drive failure happens.</p>
<p>In a way, this type of setup best represents what a novice home server enthusiast may end up with: a tiny,
power-efficient PC with a bunch of affordable drives connected.</p>
<h2 id="less-insane-storage-ideas-for-a-tiny-pc">
  <a class="heading-anchor" href="#less-insane-storage-ideas-for-a-tiny-pc">Less insane storage ideas for a tiny PC<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>There are alternative options for handling storage on a tiny 1 liter PC, but they have some downsides that I don&rsquo;t want
to be dealing with right now.</p>
<p>An USB DAS allows you to handle many drives with ease, but they are also damn expensive. If you pick wrong, you might
also end up with one
where the USB-SATA chip craps out under high load, which will momentarily drop all the drives, leaving you with a
massive headache to deal with. Cheaper USB-SATA docks are more prone to this, but I cannot confirm or deny if more
expensive options have the same issue. Running individual drives sidesteps this issue and moves any potential issues to
the host USB controller level.</p>
<p>There is also a distinct lack of solutions that are designed around 2.5&quot; drives only. Most of them are designed around
massive and power-hungry 3.5&quot; drives. I just want to run my 4 existing SATA SSD-s until they crap out completely.</p>
<p>An additional box that does stuff generally adds to the overall power consumption of the setup as well, which I am not a
big fan of. Lowering the power consumption of the setup was the whole point!</p>
<p>I can&rsquo;t rule out testing USB DAS solutions in the future as they do seem handy for adding storage to tiny PC-s and
laptops with ease, but for now I prefer going the individually connected drives route, especially because I don&rsquo;t feel
like replacing my existing drives, they still have about 94% SSD health in them after 3-4 years of use, and new drives
are <em>expensive</em>.</p>
<p>Or you could go full jank
and <a href="https://www.aliexpress.com/item/1005008295170254.html?spm=a2g0o.productlist.main.7.364fgMWRgMWR9z&amp;algo_pvid=4f0d33b6-081c-4883-8ce0-336041cc6652&amp;algo_exp_id=4f0d33b6-081c-4883-8ce0-336041cc6652-6&amp;pdp_ext_f=%7B%22order%22%3A%22116%22%2C%22eval%22%3A%221%22%7D&amp;pdp_npi=4%40dis%21EUR%2156.97%2119.37%21%21%21456.87%21155.34%21%40211b617b17491928533492865e9738%2112000044523063505%21sea%21EE%211639637618%21X&amp;curPageLogUid=uT89CAEm8INP&amp;utparam-url=scene%3Asearch%7Cquery_from%3A">use that one free NVMe slot in the tiny PC to add more SATA ports</a>
or <a href="https://www.aliexpress.com/item/1005008182661050.html?spm=a2g0o.productlist.main.7.3d7d259d5fHEIC&amp;algo_pvid=ff1d4e1e-74a8-4b65-955d-178a3eddcc71&amp;algo_exp_id=ff1d4e1e-74a8-4b65-955d-178a3eddcc71-6&amp;pdp_ext_f=%7B%22order%22%3A%2262%22%2C%22eval%22%3A%221%22%7D&amp;pdp_npi=4%40dis%21EUR%216.80%216.80%21%21%2154.52%2154.52%21%40211b61bb17491929092998623e03e6%2112000044142094508%21sea%21EE%211639637618%21X&amp;curPageLogUid=1ZzPPfnImgoi&amp;utparam-url=scene%3Asearch%7Cquery_from%3A">break out to other devices,</a>
such
as <a href="https://www.aliexpress.com/item/1005006533280553.html?spm=a2g0o.productlist.main.1.47a972a263M66x&amp;algo_pvid=02822dc1-fcb1-4b65-bb91-d022570c6388&amp;algo_exp_id=02822dc1-fcb1-4b65-bb91-d022570c6388-0&amp;pdp_ext_f=%7B%22order%22%3A%22175%22%2C%22eval%22%3A%221%22%7D&amp;pdp_npi=4%40dis%21EUR%2130.20%2128.98%21%21%21242.22%21232.43%21%40211b819117491929449653062e5f37%2112000037555851080%21sea%21EE%211639637618%21X&amp;curPageLogUid=J8ShoCWeAb85&amp;utparam-url=scene%3Asearch%7Cquery_from%3A">a PCIe HBA,</a>
and introduce a lot of clutter to the setup with an additional power supply, cables and
drives.</p>
<p>Or use 3.5&quot; external hard drives with separate power
adapters. <a href="/posts/2021/04/02/tech-tip-1/">It&rsquo;s what I actually tried out back in 2021,</a> but I had some major annoyances
with the noise.</p>
<h2 id="miscellaneous-notes">
  <a class="heading-anchor" href="#miscellaneous-notes">Miscellaneous notes<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Here are some notes on everything else that I&rsquo;ve noticed about this machine.</p>
<p>The PC is quite efficient as demonstrated by the power consumption numbers, and as a result it runs very cool, idling
around 30-35 °C in a ~22-24 °C environment. Under a heavy load, the CPU temperatures creep up to 65-70 °C, which is
perfectly acceptable. The fan does come on at higher load and it&rsquo;s definitely audible, but in my case it runs in a
ventilated closet, so I don&rsquo;t worry about that at all.</p>
<p>The CPU (Intel i5-6500T) is plenty fast for all sorts of home server workloads with its 4 CPU cores and clock speeds of
2.7-2.8 GHz under load.</p>
<p>The UEFI settings offered a few interesting options that I decided to change, the rest are set to default.</p>
<p>There is an option to enable an additional C-state for even better power savings.</p>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/c-states.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/c-states_hu_4279997e04c8a1c1.webp"
     width="1000"
     height="439"
     loading="lazy"
     decoding="async"
     alt="C-state options in UEFI settings.">

  </a>
  <figcaption class="center">C-state options in UEFI settings.</figcaption>
</figure>

<p>For home server workloads, it was nice to see the setting to allow you to boot the PC without a keyboard being attached,
found under &ldquo;Keyboardless operation&rdquo; setting. I guess that in some corporate environments disconnected keyboards are
such a common helpdesk issue that it necessitates having this option around.</p>









<figure class="center">
  <a href="/posts/2025/06/06/thinkcentre-m900-tiny/media/keyboardless-operation.jpg">
    <img src="/posts/2025/06/06/thinkcentre-m900-tiny/media/keyboardless-operation_hu_592446f591d2456f.webp"
     width="1000"
     height="427"
     loading="lazy"
     decoding="async"
     alt="Keyboardless operation setting, enabled by default.">

  </a>
  <figcaption class="center">Keyboardless operation setting, enabled by default.</figcaption>
</figure>

<h2 id="closing-thoughts">
  <a class="heading-anchor" href="#closing-thoughts">Closing thoughts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I just like these tiny PC boxes a lot. They are tiny, fast and have a very solid construction, which makes them feel
very premium in your hands. They are also perfectly usable, extensible and can be an absolute bargain at the right
price.</p>
<p>With solid power consumption figures that
are <a href="https://www.jeffgeerling.com/blog/2024/new-2gb-pi-5-has-33-smaller-die-30-idle-power-savings">only a few watts off of a Raspberry Pi 5</a>,
it might make more sense to get a TinyMiniMicro machine for your next home server. I&rsquo;m definitely very happy with mine.</p>
<h2 id="2025-06-08-update">
  <a class="heading-anchor" href="#2025-06-08-update">2025-06-08 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The USB storage idea was a bit <em>too</em> insane. I saw sporadic errors on random drives, suggesting that there is an issue
with the PC USB ports under long-term use. It wasn&rsquo;t noticeable at all until I explicitly looked at the kernel logs,
just to be safe. Good call on my part.</p>
<p>As a result, I have switched back to <a href="/posts/2024/10/16/third-times-the-charm/">my trusty ThinkPad T430.</a></p>
<p>Some logs that demonstrate the issues, collected using <code>journalctl -o short-precise -k -p 4</code>:</p>
<pre tabindex="0"><code>Jun 08 01:33:32.318310 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:33:32.318603 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:33:32.320109 lilnas kernel: I/O error, dev sdd, sector 1825796880 op 0x0:(READ) flags 0x80700 &gt;
Jun 08 01:33:32.320775 lilnas kernel: I/O error, dev sdd, sector 1825795856 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.321444 lilnas kernel: I/O error, dev sdd, sector 1825794832 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.322078 lilnas kernel: I/O error, dev sdd, sector 1825793808 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.322746 lilnas kernel: I/O error, dev sdd, sector 1825792784 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.323409 lilnas kernel: I/O error, dev sdd, sector 1825791760 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.324049 lilnas kernel: I/O error, dev sdd, sector 1825790736 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.324706 lilnas kernel: I/O error, dev sdd, sector 1825789712 op 0x0:(READ) flags 0x84700 &gt;
Jun 08 01:33:32.324736 lilnas kernel: btrfs_repair_io_failure: 982 callbacks suppressed
Jun 08 01:41:38.201307 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:41:38.201614 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:41:38.201892 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:41:38.202158 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:41:38.202529 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 01:41:38.202814 lilnas kernel: usb 2-5: cmd cmplt err -2
Jun 08 08:33:15.572984 lilnas kernel: usb 2-4: cmd cmplt err -2
</code></pre><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>well, at least it beats doom-scrolling social media.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>yeah, I don&rsquo;t like being reminded of being old, too.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>there are a lot of similarities between construction/renovation work and software development, but that&rsquo;s a story
for another time.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Home is where the home server is</title><link>https://ounapuu.ee/posts/2025/05/15/home/</link><pubDate>Thu, 15 May 2025 18:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/05/15/home/</guid><description>It was moving day, but for my home server.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/05/15/home/media/cover_hu_a66fcd5de2082142.jpg" width="1200" height="630" alt="Home is where the home server is" /><p>I moved recently, and so did my home server. You might have noticed it due to the downtime.</p>
<p>This time I have built a dedicated shelf for it, which allows for more flexibility and room for additional expensive
ideas.</p>
<p>The internet connection is a fiber line, which is fantastic for a place that&rsquo;s generally considered to be in the
countryside. I had to hire a guy at the last place in Tallinn (capital of Estonia) to pull a fiber line from the
basement to the apartment, with my own money, so I&rsquo;m very happy that I don&rsquo;t have to do it here.</p>
<p>And yes, <a href="/posts/2024/10/16/third-times-the-charm/">the ThinkPad T430 is still a solid home server.</a>
I had an issue with my battery calibration script resulting in the machine being turned off, but I fixed it by disabling
it, at the cost of the battery probably dying soon. Seems like a <code>tlp</code> and/or Linux kernel issue that has surfaced
recently, as it also happened on a different ThinkPad laptop when I last tried it. I can&rsquo;t really remove the battery,
because the &ldquo;power on with AC attach&rdquo; setting only works when the battery is connected and charged.</p>
<p>The server/wardrobe/closet room is slightly chillier compared to the rest of the environment, meaning that the
temperatures are also slightly lower. I also have an option to do some crazy ventilation experiments in the winter, but
that will have to wait for a bit, mainly because it&rsquo;s spring.</p>
<p>I&rsquo;m genuinely surprised that the Wi-Fi 5 signal is coming through the closet quite adequately, with the whole apartment
being covered with at least 50 Mbit/s speeds, and over 300 Mbit/s when near the closet, which is about the maximum speed
that I can achieve from the access point in ideal conditions.</p>
]]></content:encoded></item><item><title>I yearn for the perfect home server</title><link>https://ounapuu.ee/posts/2025/03/07/perfect-home-server/</link><pubDate>Fri, 07 Mar 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/03/07/perfect-home-server/</guid><description>I've thought a lot about the performance, cost and power consumption trade-offs of home servers. Maybe too much.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/03/07/perfect-home-server/media/cover_hu_81094fb88b6730e7.jpg" width="1200" height="630" alt="I yearn for the perfect home server" /><p>I&rsquo;ve changed my home server setup a lot over the past
decade, <a href="/posts/2023/10/25/the-optimization-treadmill/">mainly because I keep changing the goals all the time.</a></p>
<p>I&rsquo;ve now realized why that keeps happening.</p>
<p>I want <em><strong>the perfect home server.</strong></em></p>
<p>What <em>is</em> the perfect home server? I&rsquo;d phrase it like this:</p>
<blockquote>
<p>The perfect home server uses very little power, offers plenty of affordable storage and provides a lot of performance
when it&rsquo;s actually being relied upon.</p>
</blockquote>
<p>In my case, low power means less than 5 W while idling, 10+ TB of redundant storage for data resilience and integrity
concerns, and performance means about 4 modern CPU cores&rsquo; worth (low-to-midrange desktop CPU performance). I seem to
only ever get one or two at most.</p>
<p>Low power usage? Your performance will likely suffer, and you can&rsquo;t run too many storage drives. You <em>can</em> run SSD-s,
but they are not affordable if you need higher capacities.</p>
<p>Lots of storage? Well, there goes the low power consumption goal, especially if you run 3.5&quot; hard drives.</p>
<p>Lots of performance? Lots of power consumed!</p>
<p>There&rsquo;s just something that annoys me whenever I do things on my home server and I have to wait longer than I should,
and yet I&rsquo;m
bothered <a href="/posts/2024/05/02/smartplugs/">when my monitoring tells me that my home server is using 50+ watts.</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>I keep an eye out for developments in the self-hosting and home server spaces with the hopes that I&rsquo;ll one day stumble
upon the holy grail, that one server that fits all my needs. <a href="/posts/2023/10/09/zimaboard/">I&rsquo;ve gotten close</a>, but
no matter what setup I have, there&rsquo;s always something that keeps bothering me.</p>
<p>I&rsquo;ve seen a few attempts at the perfect home server, covered by various tech reviewers, but they always have at least
one critical flaw. Sometimes the whole package is actually great, the functionality rocks, and then you find that the
hardware contains prototype-level solutions that result in the power consumption ballooning to over 30 W. Or the price
is over 1000 USD/EUR, not including the drives. Or it&rsquo;s only available in certain markets and the shipping and import
duties destroy its value proposition.</p>
<p>There is no affordable platform out there that provides great performance, flexibility and storage space, all while
being quiet and using very little power.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Desktop PC-s repurposed as home servers can provide room for a lot of storage, and they are by design very flexible, but
the trade-off is the higher power consumption of the setup.</p>
<p><a href="https://www.jeffgeerling.com/blog/2024/radxas-sata-hat-makes-compact-pi-5-nas">Single board computers</a> use very little
power, but they can&rsquo;t provide a lot of performance and connecting storage to them gets tricky and is overall limited.
They can also get <a href="https://www.jeffgeerling.com/blog/2025/who-would-buy-raspberry-pi-120">surprisingly expensive.</a></p>
<p>NAS boxes provide a lot of storage space and are generally low power if you exclude the power consumption of hard
drives, but the cheaper ones are not that performant, and the performant ones cost almost as much as a high-end PC.</p>
<p><a href="/posts/2024/10/16/third-times-the-charm/">Laptops can be used as home servers,</a> they are quite efficient and
performant, but they lack the flexibility and storage options of desktop PC-s and NAS boxes. You can slap a USB-based
DAS to it to add storage, but I&rsquo;ve had poor experiences with these under high load, meaning that these approaches can&rsquo;t
be relied on if you care about your data and server stability.</p>
<p>Then there&rsquo;s the option of buying used versions of all of the above. Great bang for buck, but you&rsquo;re likely taking a hit
on the power efficiency part due to the simple fact that technology keeps evolving and getting more efficient.</p>
<p>I&rsquo;m still hopeful that one day a device exists that ticks all the boxes while also being priced affordably, but I&rsquo;m
afraid that it&rsquo;s just a pipe
dream. <a href="https://mattgadient.com/7-watts-idle-on-intel-12th-13th-gen-the-foundation-for-building-a-low-power-server-nas/">There are builds out there that fill in almost every need</a>,
but the parts list is very specific and the bulk of the power consumption wins come from using SSD-s instead of hard
drives, which makes it less affordable.</p>
<p>In the meantime I guess I&rsquo;ll keep rocking <a href="/posts/2024/10/16/third-times-the-charm/">my ThinkPad-as-a-server approach</a>
and praying that the USB-attached storage does not cause major issues.</p>









<figure class="center">
  <a href="/posts/2025/03/07/perfect-home-server/media/powerconsumption.png">
    <img src="/posts/2025/03/07/perfect-home-server/media/powerconsumption_hu_a7a2d57724d8abf2.webp"
     width="1000"
     height="693"
     loading="lazy"
     decoding="async"
     alt="My whole home server infrastructure power consumption, including the fiber converter box and the wireless router.">

  </a>
  <figcaption class="center">My whole home server infrastructure power consumption, including the fiber converter box and the wireless router.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2025/03/07/perfect-home-server/media/powerconsumption-per-day.png">
    <img src="/posts/2025/03/07/perfect-home-server/media/powerconsumption-per-day_hu_413132197591747d.webp"
     width="1000"
     height="693"
     loading="lazy"
     decoding="async"
     alt="On typical days I can see power consumption of around 0.7 kWh per day, resulting in 21 kWh used within a month.">

  </a>
  <figcaption class="center">On typical days I can see power consumption of around 0.7 kWh per day, resulting in 21 kWh used within a month.</figcaption>
</figure>

<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>perhaps it&rsquo;s an undiagnosed medical condition. <em>Homeserveritis?</em>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>if there <em>is</em> one, then let me know, you can find the contact details below!&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Why my blog was down for over 24 hours in November 2024</title><link>https://ounapuu.ee/posts/2025/01/21/downtime/</link><pubDate>Tue, 21 Jan 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/01/21/downtime/</guid><description>Everything I learned from an incident that made me consider switching careers. It was a close one!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/01/21/downtime/media/cover_hu_e9bbb9d03e5c963f.jpg" width="1200" height="630" alt="Why my blog was down for over 24 hours in November 2024" /><p>In November 2024, my blog was down for over 24 hours.</p>
<p>Here&rsquo;s what I learned from this absolute clusterfuck of an incident.</p>
<h2 id="lead-up-to-the-incident">
  <a class="heading-anchor" href="#lead-up-to-the-incident">Lead-up to the incident<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I was browsing through photos on my <a href="https://nextcloud.com/">Nextcloud</a> instance. Everything was fine, until Nextcloud
started generating preview images for older photos.
This process is quite resource intensive, but generally manageable. However, this time the images were high quality
photos in the 10-20 MB size range.</p>
<p>Nextcloud crunched through those, but ended up spawning so many processes that it ended up using all the available
memory on my home server.</p>









<figure class="center">
  <a href="/posts/2025/01/21/downtime/media/oom.png">
    <img src="/posts/2025/01/21/downtime/media/oom_hu_a7bb1706f8142c5e.webp"
     width="577"
     height="278"
     loading="lazy"
     decoding="async"
     alt="Uh-oh.">

  </a>
  <figcaption class="center">Uh-oh.</figcaption>
</figure>

<p>And thus, the server was down.</p>
<p>This could have been solved by a forced reboot. Things were complicated by the simple fact that I was 120 kilometers
away from my server, and I had no IPMI-like device set up.</p>
<p>So I waited.</p>
<p>50 minutes later, I successfully logged in to my server over SSH again! The load averages were in the three-digit realm,
but the system was mostly operational.</p>









<figure class="center">
  <a href="/posts/2025/01/21/downtime/media/loadaverage.png">
    <img src="/posts/2025/01/21/downtime/media/loadaverage_hu_33a3a2e52fb68add.webp"
     width="548"
     height="279"
     loading="lazy"
     decoding="async"
     alt="Load average after logging in after the out of memory incident, shown with htop.">

  </a>
  <figcaption class="center">Load average after logging in after the out of memory incident, shown with htop.</figcaption>
</figure>

<p>I thought that it would be a good idea to restart the server, since who knows what might&rsquo;ve gone wrong while the server
was handling the out-of-memory situation.</p>
<p>I reboot.</p>
<p>The server doesn&rsquo;t seem to come back up. Fuck.</p>









<figure class="center">
  <a href="/posts/2025/01/21/downtime/media/reboot.png">
    <img src="/posts/2025/01/21/downtime/media/reboot_hu_d91afcae7d436db8.webp"
     width="950"
     height="278"
     loading="lazy"
     decoding="async"
     alt="Kurwa.">

  </a>
  <figcaption class="center">Kurwa.</figcaption>
</figure>

<h2 id="the-downtime">
  <a class="heading-anchor" href="#the-downtime">The downtime<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The worst part of the downtime was that I was simply unable to immediately fix it due to being 120 kilometers away from
the server.</p>
<p>My VPN connection back home was also hosted right there on the server,
using <a href="https://hub.docker.com/r/linuxserver/wireguard">this Docker image.</a></p>
<p>I eventually got around to fixing this issue the next day when I could finally get hands-on with the
server, <a href="/posts/2024/10/16/third-times-the-charm/">my trusty ThinkPad T430.</a>
I open the lid and am greeted with the console login screen. This means that the machine <em>did</em> boot.</p>
<p>I log in to the server over SSH and quickly open <code>htop</code>. My <code>htop</code> configuration shows metrics like <code>systemd</code> state, and
it was showing 20+ failed services. This is very unusual.</p>
<p><code>lsblk</code> and <code>mount</code> show that the storage is there. What was the issue?</p>
<p>Well, apparently the Docker daemon was not starting. I was searching for the error messages and ended
up <a href="https://github.com/moby/moby/issues/21215#issuecomment-568445170">on this GitHub issue.</a>
I tried the fix, which involved deleting the Docker folder with all the containers and configuration, and restarted the
daemon and containers. Everything is operational once again.</p>
<p>I then rebooted the server.</p>
<p>Everything is down again, with the same issue.</p>
<p>And thus began a 8+ hours long troubleshooting session that ran late into the night. <em>04:00-ish</em> late, on a Monday.</p>
<p>I tried everything that I could come up with:</p>
<ul>
<li>used the <code>btrfs</code> Docker storage driver instead of the default overlay one
<ul>
<li>Docker is still broken after a reboot</li>
</ul>
</li>
<li>replaced everything with <code>podman</code>
<ul>
<li>I could not get <code>podman</code> to play well with my containers and IPv6 networking</li>
</ul>
</li>
<li>considered switching careers
<ul>
<li>tractors are surprisingly expensive!</li>
</ul>
</li>
</ul>
<p>I&rsquo;m unable to put into words how frustrating this troubleshooting session was. The sleep deprivation, the lack of
helpful information, the failed attempts at finding solutions. I&rsquo;m usually quite calm and very rarely feel anger,
but during these hours I felt <em><strong>enraged.</strong></em></p>
<h2 id="the-root-cause">
  <a class="heading-anchor" href="#the-root-cause">The root cause<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The root cause will make more sense after you understand the storage setup I had at the time.</p>
<p>The storage on my server consisted of four 4 TB SSD-s, two were mounted inside the laptop, and the remaining two were
connected via USB-SATA adapters. The filesystem in use was <code>btrfs</code>, both on the OS drive and the 4x 4TB storage pool. To
avoid
hitting the OS boot drive with unnecessary writes, I moved the Docker data root to a separate <code>btrfs</code> subvolume on the
main storage pool.</p>
<p>What was the issue?</p>
<p>Apparently the Docker daemon on Fedora Server is able to start up <em><strong>before every filesystem was mounted.</strong></em> In this
case, Docker daemon started up before the subvolume containing all the Docker images, containers and networks was
mounted.</p>
<p>I tested out this theory by moving the Docker storage back to <code>/var/lib/docker</code>, which lives on the root filesystem, and
after a reboot everything remained functional.</p>
<p>In the past, I ran a similar setup, but with the Docker storage on the SATA SSD-s that are mounted inside the laptop
over a native SATA connection. With the addition of two USB-connected SSD-s, the mounting process took longer for the
whole pool, which resulted in a race condition between the Docker daemon startup and the storage being mounted.</p>
<h2 id="fixing-the-root-cause">
  <a class="heading-anchor" href="#fixing-the-root-cause">Fixing the root cause<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The fix for Docker starting up before all of your storage is mounted is actually quite elegant.</p>
<p>The Docker service definition is contained in <code>/etc/systemd/system/docker.service</code>. You can override this configuration
by creating a new directory at <code>/etc/systemd/system/docker.service.d</code> and dropping a file with the name <code>override.conf</code>
in there with the following contents:</p>
<pre tabindex="0"><code>[Unit]
RequiresMountsFor=/containerstorage
</code></pre><p>The rest of the service definition remains the same and your customized configuration won&rsquo;t be overwritten with a Docker
version update. The <code>RequiresMountsFor</code> setting prevents the Docker service from starting up before that particular
mount exists.</p>
<p>You can specify multiple mount points on the same line, separated by spaces.</p>
<pre tabindex="0"><code>[Unit]
RequiresMountsFor=/containerstorage /otherstorage /some/other/mountpoint
</code></pre><p>You can also specify the mount points over multiple lines if you prefer.</p>
<pre tabindex="0"><code>[Unit]
RequiresMountsFor=/containerstorage 
RequiresMountsFor=/otherstorage 
RequiresMountsFor=/some/other/mountpoint
</code></pre><p>If you&rsquo;re using <code>systemd</code> unit files for controlling containers, then you can use the same <code>systemd</code> setting to prevent
your containers from starting up before the storage that the container depends on is mounted.</p>
<h2 id="avoiding-the-out-of-memory-incident">
  <a class="heading-anchor" href="#avoiding-the-out-of-memory-incident">Avoiding the out of memory incident<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Nextcloud taking down my home server for 50 minutes was not the root cause, it only highlighted an issue that had been
there for days at that point. That doesn&rsquo;t mean that this area can&rsquo;t be improved.</p>
<p>After this incident, every Docker Compose file that I use includes resource limits on all containers.</p>
<p>When defining the limits, I started with very conservative limits based on the average resource usage as observed from
<code>docker stats</code> output.</p>
<p>Over the past few months I&rsquo;ve had to continuously tweak the limits, especially the memory ones, due to the containers
themselves running out of memory when the limits were set too low. Apparently software is getting increasingly more
resource hungry.</p>
<p>An example Docker Compose file with resource limits looks like this:</p>
<pre tabindex="0"><code>name: nextcloud
services:
  nextcloud:
    container_name: nextcloud
    volumes:
      - /path/to/nextcloud/stuff:/data
    deploy:
      resources:
        limits:
          cpus: &#34;4&#34;
          memory: 2gb
    image: docker.io/nextcloud:latest
    restart: always
  nextcloud-db:
    container_name: nextcloud-db
    volumes:
      - /path/to/database:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          cpus: &#34;4&#34;
          memory: 2gb
    image: docker.io/postgres:16
    restart: always
</code></pre><p>In this example, each container is able to use up to 4 CPU cores and a maximum of 2 GB of memory. And just like that,
Nextcloud is unable to take down my server by eating up all the available memory.</p>
<p>Yes, I&rsquo;m aware of the <a href="https://github.com/nextcloud/previewgenerator">Preview Generator Nextcloud app.</a> I have it, but
over multiple years of running Nextcloud, I have not found it to be very effective against the resource-hungry preview
image generation happening during user interactions.</p>
<h2 id="decoupling-my-vpn-solution-from-docker">
  <a class="heading-anchor" href="#decoupling-my-vpn-solution-from-docker">Decoupling my VPN solution from Docker<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With this incident, it was also clear that running your gateway to your home network inside a container was a really
stupid idea.</p>
<p>I&rsquo;ve mitigated this issue by taking the WireGuard configuration generated by the container and moving it to the host. I
also used this as an opportunity to get a to-do list item done and
used <a href="https://stanislas.blog/2019/01/how-to-setup-vpn-server-wireguard-nat-ipv6/">this guide</a> to add IPv6 support inside
the
virtual WireGuard network. I can now access IPv6 networks everywhere I go!</p>
<p>I briefly considered setting WireGuard up on my openWRT-powered router, but I decided against it as I&rsquo;d like to own
one computer that I don&rsquo;t screw up with my configuration changes.</p>
<h2 id="closing-thoughts">
  <a class="heading-anchor" href="#closing-thoughts">Closing thoughts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have not yet faced an incident this severe, even at work. The impact wasn&rsquo;t that big, I guess a hundred people
were not able to read my blog, but the stress levels were off the charts for me during the troubleshooting process.</p>
<p>I&rsquo;ve long advocated for self-hosting and running basic and boring solutions, with the main benefits being ease of
maintenance, troubleshooting and low cost. This incident is a good reminder that even the most basic setups can have
complicated issues associated with them.</p>
<p>At least I got it fixed and learned about a new <code>systemd</code> unit setting, which is nice.</p>
<p>Still better than handling <a href="/posts/2024/10/01/kubernetes/">Kubernetes</a> <a href="/posts/2024/04/04/helm-rollbljat/">issues.</a></p>
]]></content:encoded></item><item><title>The IPv6 situation on Docker is good now!</title><link>https://ounapuu.ee/posts/2024/12/20/docker-ipv6/</link><pubDate>Fri, 20 Dec 2024 19:30:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/12/20/docker-ipv6/</guid><description>It's not often when a piece of software has genuinely improved, which is why this is worth celebrating!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/12/20/docker-ipv6/media/cover_hu_2d1118bf85d813df.jpg" width="1200" height="630" alt="The IPv6 situation on Docker is good now!" /><p>Good news, everyone! Doing IPv6 networking stuff on Docker is actually good now!</p>
<p>I&rsquo;ve recently started reworking my home server setup to be more IPv6 compatible, and as part of that I learned that
during
the summer of 2024 <a href="https://docs.docker.com/engine/release-notes/27/#ipv6">Docker shipped an update</a> that eliminated a
lot of the configuration and tweaking previously necessary
to support IPv6.</p>
<p>There is no need to change the daemon configuration any longer, it just works on Docker Engine v27 and later.</p>
<h2 id="examples">
  <a class="heading-anchor" href="#examples">Examples<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If your host has a working IPv6 setup and you want to listen to port 80 on both IPv4 and IPv6, then you don&rsquo;t
have to do anything special. However, the container will only have an IPv4 address internally.
You can verify it by listing all the Docker networks via <code>sudo docker network ls</code> and running
<code>sudo docker network inspect network-name-here</code> for the one associated with your container.</p>
<p>For services like <code>nginx</code> that log the source IP address, this is problematic, as every incoming IPv6 request will be
logged with the Docker network gateway IP address, such as <code>10.88.0.1</code>.</p>
<pre tabindex="0"><code>name: nginx
services:
  nginx:
    container_name: nginx
    ports:
      - 80:80
    image: docker.io/library/nginx
    restart: always
</code></pre><p>If you want the container to have an IPv4 <em>and</em> an IPv6 address within the Docker network, you can create a new network
and enable IPv6 in it.</p>
<pre tabindex="0"><code>name: nginx
services:
  nginx:
    container_name: nginx
    networks:
      - nginx-network
    ports:
      - 80:80
    image: docker.io/library/nginx
    restart: always
networks:
  nginx-network:
    enable_ipv6: true
</code></pre><p>There are situations where it&rsquo;s handy to have a static IP address for a container within the Docker network.
If you need help coming up with an unique local IPv6 address range, you
can <a href="https://unique-local-ipv6.com/">use this tool.</a></p>
<pre tabindex="0"><code>name: nginx
services:
  nginx:
    container_name: nginx
    networks:
      nginx-network
        ipv4_address: 10.69.42.5
        ipv6_address: fdec:cc68:5178::abba
    ports:
      - 80:80
    image: docker.io/library/nginx
    restart: always
networks:
  nginx-network:
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: &#34;10.69.42.0/24&#34;
        - subnet: &#34;fdec:cc68:5178::/64&#34;
</code></pre><p>If you choose the <a href="https://docs.docker.com/engine/network/drivers/host/">host network driver,</a> your container will
operate within the same networking space as your container host. If the host handles both IPv4 and IPv6 networking, then
your container will happily operate with both. However, due to reduced network isolation, this has some security
implications that you must take into account.</p>
<pre tabindex="0"><code>name: nginx
services:
  nginx:
    container_name: nginx
    network_mode: host
    # ports are not relevant with host network mode
    image: docker.io/library/nginx
    restart: always
</code></pre><p>If you want your container to only accept connections on select interfaces, such as a Wireguard connection, then you will need
to specify the IP addresses in the <code>ports</code> section. Here&rsquo;s one example with both IPv4 and IPv6.</p>
<pre tabindex="0"><code>name: nginx
services:
  nginx:
    container_name: nginx
    networks:
      - nginx-network
    ports:
      - 10.69.42.5:80:80
      - &#34;[fdec:cc68:5178::beef]:80:80&#34;
    image: docker.io/library/nginx
    restart: always
networks:
  nginx-network:
    enable_ipv6: true
</code></pre><h2 id="what-about-podman">
  <a class="heading-anchor" href="#what-about-podman">What about Podman?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;ve given up on Podman. Before doing things the IPv6 way, Podman was functional for the most part, requiring a few
tweaks to get things working.</p>
<p>I have not managed to get Podman to play fair with IPv6. No matter what I did, I could not get it to listen to certain
ports and access my services, the ports would always be filtered out.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;m genuinely happy to see that the IPv6 support has gotten better with Docker, and I hope that this short introduction
helps those out there looking to do things the IPv6 way with containers.</p>
]]></content:encoded></item><item><title>How to build a fleet of networked offsite backups using Linux, WireGuard and rsync</title><link>https://ounapuu.ee/posts/2024/12/11/wireguard-backup-fleet/</link><pubDate>Wed, 11 Dec 2024 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/12/11/wireguard-backup-fleet/</guid><description>You have offsite backups of your most important data, right? Right???</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/12/11/wireguard-backup-fleet/media/cover_hu_79c3c1903608e4ea.jpg" width="1200" height="630" alt="How to build a fleet of networked offsite backups using Linux, WireGuard and rsync" /><p>Just like most people out there, I have some files that are irreplaceable, such as cat pictures.</p>
<p>At one point I had a few single-board computers sitting idle, namely
the <a href="http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero.html">Orange Pi Zero</a> and
the <a href="https://www.lattepanda.com/lattepanda-v1">LattePanda V1</a>, and a few
1TB SSD-s.</p>
<p>I hate idle hardware, so I did the most sensible thing and assembled a fleet of networked offsite backups for
backing up the most important data.</p>
<p>My setup is based on various flavors of Linux, but the ideas will likely translate well onto other operating systems
and solutions.</p>
<h2 id="networking">
  <a class="heading-anchor" href="#networking">Networking<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The most important part is the networking. The offsite backup endpoints connect together to my home server over a
WireGuard network. The home server is, well, <em>the server</em>, and backup endpoints are clients.</p>
<p>I like <a href="https://github.com/linuxserver/docker-WireGuard">this WireGuard Docker image</a> a lot because it generates
the server and client configurations automatically, but you can use plain WireGuard or a completely different networking
solution to connect all the devices together. Some use Tailscale to make the setup process easier, but I like to keep
things as self-hosted as possible.</p>
<p>I&rsquo;m not a networking expert, but here&rsquo;s how I&rsquo;ve set up my network. For this example, the WireGuard network operates in
the <code>10.13.69.0/24</code> range.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>To only allow traffic between the devices and avoid tunneling everything through the home server, set the <code>AllowedIPs</code>
setting to <code>AllowedIPs = 10.13.69.0/24,10.13.69.1</code>. We want to be able to access the backup endpoints, and nothing more.</p>
<p>All the devices have a static IP address in that network, such as <code>10.13.69.1</code> for the home server, <code>10.13.69.2</code> for a
backup endpoint and so on.</p>
<p>The <code>PersistentKeepalive = 25</code> option is present in the client configurations so that I don&rsquo;t lose the ability to access
the backup endpoints. With it, all the backup endpoints call back to the home server from time to time. The
aforementioned Docker image automatically adds it to the generated configuration using
the <code>PERSISTENTKEEPALIVE_PEERS=all</code> option.
This setting is <em><strong>crucial.</strong></em> Without it, I sometimes ran into problems trying to connect from my home server to the
backup endpoint, and that&rsquo;s something you can&rsquo;t easily alleviate without having physical access to the backup endpoints,
which are offsite.</p>
<p>Remove the DNS configuration from generated WireGuard client configurations, as you don&rsquo;t need it for this purpose.</p>
<p>Optionally, edit the <code>/etc/hosts</code> file for the home server and backup endpoints so that you can access your backup
endpoints using simple hostnames, like <code>orangepizero</code>. Example row can look like this: <code>10.13.69.6 orangepizero</code>.</p>
<p>if your WireGuard server operates in a network with a dynamic external IP address, as is common with many home internet
connections, I recommend getting yourself a domain name that you can update whenever your IP address changes and using
that in your WireGuard client configurations. Without this, an IP address change will result in your backup endpoints
being inaccessible.</p>
<p>You&rsquo;ll also likely need to set up port forwarding and/or traffic rules for your backup endpoints to be able to connect
back to your WireGuard server.</p>
<p>Once you have the WireGuard connection set up and SSH running on the backup endpoints, you should be able to drop the
backup endpoints into any network that you have permission for. Ask your friends and family, and sweeten the deal by
offering free technical support or help in some other area in return. The cost of running a single-board computer 24/7
is minuscule with the typical power consumption being 1-3W, so that won&rsquo;t be much of a concern.</p>
<h2 id="making-backups">
  <a class="heading-anchor" href="#making-backups">Making backups<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>For making the actual backups themselves, you have all sorts of options.</p>
<p>I rely on <code>rsync</code> to copy the data over. It&rsquo;s simple and it works, that&rsquo;s all I expect from it.
Example command: <code>rsync -aAXvz /folder/to/back/up/ backupuser@backupendpoint:/backup/ --delete</code>.
The files will be compressed during transit with the <code>-z</code> option, and with <code>--delete</code> you&rsquo;ll ensure that the target
folder has all the files from the source, and nothing else.</p>
<p>The backup storage is specified in <code>/etc/fstab</code> with the <code>nofail</code> option present. This ensures that in case the disk
dies, the backup endpoint will still boot properly, allowing me to access the machine to troubleshoot the issue and/or
force a desperate reboot to try to fix things. A good alternative approach is to mount/unmount the remote disk manually
as part
of the backup script.</p>
<p>The backup storage uses the <code>btrfs</code> filesystem, and I use <code>btrbk</code> to take snapshots of the contents. If I accidentally
delete all the files on the backup endpoint, then I can still recover from that situation because the data is still
present in snapshots. 30 days is a good retention period: enough time to save the data in case of an accidental
deletion, but short
enough to avoid the backup disk getting full.</p>
<p>If you don&rsquo;t want to use filesystem-level snapshots, then tools like <code>restic</code> are a good alternative. It can also
operate
over SSH and you can configure snapshot retention policies in your backup script. Just make sure to not lose the
encryption password, and
verify the backups once in a while.</p>
<h2 id="deployment">
  <a class="heading-anchor" href="#deployment">Deployment<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I manage my backup endpoints using some cobbled-together Ansible roles. I&rsquo;ve perfected it to the point where the only
manual
steps are flashing the OS and setting up the storage, the rest is handled via Ansible.</p>
<p>I&rsquo;d like to share my work here, but it will make Jeff Geerling cry. Maybe one day I&rsquo;ll take the time to improve
things&hellip;</p>
<h2 id="maintenance">
  <a class="heading-anchor" href="#maintenance">Maintenance<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>All the backup endpoints update and reboot themselves regularly. It&rsquo;s just the sensible thing to do.</p>
<p>Every 6-12 months I also do major OS version updates. It&rsquo;s risky because of the whole offsite aspect of the solution,
but so far I haven&rsquo;t been burned yet.</p>
<h2 id="monitoring">
  <a class="heading-anchor" href="#monitoring">Monitoring<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Monitoring is an area where I have some room for improvement. So far, I&rsquo;ve set up Prometheus node-exporter to all of
the backup endpoints, and my home server keeps track of how the backup endpoints are doing.</p>
<p>This allows me to check once in a while if any of the backup endpoints has fallen off the network, or if the backup disk
is getting full.</p>
<h2 id="issues-ive-faced">
  <a class="heading-anchor" href="#issues-ive-faced">Issues I&rsquo;ve faced<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;ve had this system running for a few years now, and it&rsquo;s mostly stable! There have been some issues I&rsquo;ve faced as
well,
though. Some are very specific to certain hardware, but I think there&rsquo;s value in mentioning them.</p>
<p><a href="/posts/2023/06/10/how-i-blew-up-my-backup-server/">I once blew up a backup server because of an Ansible configuration issue.</a>
That meant that I had to physically go pick up the server to re-image it.</p>
<p>The Orange Pi Zero was running quite hot, resulting in stability issues, so I put together a really janky cooling
solution.</p>









<figure class="center">
  <a href="/posts/2024/12/11/wireguard-backup-fleet/media/orangepizero.jpg">
    <img src="/posts/2024/12/11/wireguard-backup-fleet/media/orangepizero_hu_689cb39c9001c4e2.webp"
     width="750"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Cooling. It works.">

  </a>
  <figcaption class="center">Cooling. It works.</figcaption>
</figure>

<p>Hell, I did the same for the LattePanda as well.</p>









<figure class="center">
  <a href="/posts/2024/12/11/wireguard-backup-fleet/media/lattepanduh.jpg">
    <img src="/posts/2024/12/11/wireguard-backup-fleet/media/lattepanduh_hu_b5634f62aec46ed4.webp"
     width="1000"
     height="750"
     loading="lazy"
     decoding="async"
     alt="First version of the cooling upgrade on the LattePanda.">

  </a>
  <figcaption class="center">First version of the cooling upgrade on the LattePanda.</figcaption>
</figure>

<p>It might look horrific but the extra cooling has fixed all the stability problems on both boards.</p>
<p>The lack of a real-time clock on the LattePanda has required me to make its backup script a bit special. I can&rsquo;t rely on
a systemd timer that automatically reboots the machine once in a while, so instead that part is present in the backup
script. The issue is that the LattePanda boots up with the time being set in the past, and once it gets the actual time
from the
network, it will run all sorts of tasks because enough time has passed!
This included the reboot timer as well.</p>
<p>At one point, the power supply on the LattePanda just died, and it was very visible on my graphs. That required a
replacement.</p>









<figure class="center">
  <a href="/posts/2024/12/11/wireguard-backup-fleet/media/lattepanda-psu-failure.png">
    <img src="/posts/2024/12/11/wireguard-backup-fleet/media/lattepanda-psu-failure_hu_83ab55cb07768116.webp"
     width="1000"
     height="725"
     loading="lazy"
     decoding="async"
     alt="Signs that you might have a failing power supply.">

  </a>
  <figcaption class="center">Signs that you might have a failing power supply.</figcaption>
</figure>

<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>That&rsquo;s how I back up the most important data. I hope that this has given you inspiration to take your own backup
approach to the next level!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>yes, I do plan to move this setup to IPv6 eventually.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Your Wi-Fi might be terrible because of Dynamic Frequency Selection (DFS)</title><link>https://ounapuu.ee/posts/2024/11/11/openwrt-dfs/</link><pubDate>Mon, 11 Nov 2024 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/11/11/openwrt-dfs/</guid><description>My Wi-Fi kept dropping out until I learned about this fun little feature. Here's how to fix it for good.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/11/11/openwrt-dfs/media/cover_hu_922176fce2414a28.jpg" width="1200" height="630" alt="Your Wi-Fi might be terrible because of Dynamic Frequency Selection (DFS)" /><p>For a few months, I had issues with my Wi-Fi network. The 2.4 GHz network would be fine, but the 5 GHz one would
suddenly stop working and completely disappear from the available Wi-Fi networks. OpenWRT upgrades also didn&rsquo;t improve
the situation. This was very annoying.</p>
<p>After some discussions with a friend, I learned
about <a href="https://en.wikipedia.org/wiki/Dynamic_frequency_selection">Dynamic Frequency Selection (DFS).</a> Apparently some
channels on the 5 GHz Wi-Fi spectrum are also used by weather and military radars, and those take priority. If such
interference is detected, your Wi-Fi access point should switch to a different channel.</p>
<p>It turns out that some implementations are buggy and mine is one of them.</p>
<p>One quick but permanent fix is to manually select a Wi-Fi channel to operate in.</p>
<p>With OpenWRT, you can get a list of all the available Wi-Fi channels using this command:</p>
<pre tabindex="0"><code>iw list | grep dBm
</code></pre><p>Example output:</p>
<pre tabindex="0"><code>* 2412 MHz [1] (20.0 dBm)
* 2417 MHz [2] (20.0 dBm)
* 2422 MHz [3] (20.0 dBm)
* 2427 MHz [4] (20.0 dBm)
* 2432 MHz [5] (20.0 dBm)
* 2437 MHz [6] (20.0 dBm)
* 2442 MHz [7] (20.0 dBm)
* 2447 MHz [8] (20.0 dBm)
* 2452 MHz [9] (20.0 dBm)
* 2457 MHz [10] (20.0 dBm)
* 2462 MHz [11] (20.0 dBm)
* 2467 MHz [12] (20.0 dBm)
* 2472 MHz [13] (20.0 dBm)
* 5180 MHz [36] (23.0 dBm)
* 5200 MHz [40] (23.0 dBm)
* 5220 MHz [44] (23.0 dBm)
* 5240 MHz [48] (23.0 dBm)
* 5260 MHz [52] (20.0 dBm) (radar detection)
* 5280 MHz [56] (20.0 dBm) (radar detection)
* 5300 MHz [60] (20.0 dBm) (radar detection)
* 5320 MHz [64] (20.0 dBm) (radar detection)
* 5500 MHz [100] (26.0 dBm) (radar detection)
* 5520 MHz [104] (26.0 dBm) (radar detection)
* 5540 MHz [108] (26.0 dBm) (radar detection)
* 5560 MHz [112] (26.0 dBm) (radar detection)
* 5580 MHz [116] (26.0 dBm) (radar detection)
* 5600 MHz [120] (26.0 dBm) (radar detection)
* 5620 MHz [124] (26.0 dBm) (radar detection)
* 5640 MHz [128] (26.0 dBm) (radar detection)
* 5660 MHz [132] (26.0 dBm) (radar detection)
* 5680 MHz [136] (26.0 dBm) (radar detection)
* 5700 MHz [140] (26.0 dBm) (radar detection)
* 5720 MHz [144] (13.0 dBm) (radar detection)
* 5745 MHz [149] (13.0 dBm)
* 5765 MHz [153] (13.0 dBm)
* 5785 MHz [157] (13.0 dBm)
* 5805 MHz [161] (13.0 dBm)
* 5825 MHz [165] (13.0 dBm)
* 5845 MHz [169] (13.0 dBm)
* 5865 MHz [173] (13.0 dBm)
</code></pre><p>Notice the ones with <code>(radar detection)</code> at the end? Those are the potentially problematic channels. We&rsquo;re going to
avoid them from now on by picking a specific channel to use.</p>
<p>When it comes to the choice of the channels themselves, you&rsquo;ll also have to consider the channel width. If you pick a
channel next to one of the radar detection ones and with a large channel width, you might still run into issues.</p>
<p>Choosing a specific channel also comes with bandwidth and range trade-offs. If you don&rsquo;t care much for those, go for the
lowest one and with 40 MHz width. Picking the optimal Wi-Fi channel and channel width configuration for your specific
needs is better explained by other resources.</p>









<figure class="center">
  <a href="/posts/2024/11/11/openwrt-dfs/media/openwrt-luci.png">
    <img src="/posts/2024/11/11/openwrt-dfs/media/openwrt-luci_hu_762e2ab7b34fdf81.webp"
     width="902"
     height="462"
     loading="lazy"
     decoding="async"
     alt="Choosing a specific channel in OpenWRT using the GUI (LuCI).">

  </a>
  <figcaption class="center">Choosing a specific channel in OpenWRT using the GUI (LuCI).</figcaption>
</figure>

<p>I recommend getting a Wi-Fi spectrum analysis app that shows you the channels that are least populated by neighboring
Wi-Fi access points.</p>
<p>It is also possible to define the list of channels that the Wi-Fi AP can automatically choose from using the <code>channels</code>
option for the wireless interface. We can use this setting to avoid the radar detection channels completely. This
setting doesn&rsquo;t seem to be configurable via the graphical interface (LuCI), but you can change it
in <code>/etc/config/wireless</code> using the command line and <code>vi</code>, over SSH.</p>
<p>More information about this option and others can be found
in <a href="https://openwrt.org/docs/guide-user/network/wifi/basic#common_options">OpenWRT documentation.</a></p>
<p>Based on our example, a configuration that avoids radar detection frequencies can look something like this:</p>
<pre tabindex="0"><code>config wifi-device &#39;radio0&#39;
        option type &#39;mac80211&#39;
        option path &#39;pci0000:00/0000:00:00.0&#39;
        option channel &#39;auto&#39;
        option channels &#39;36 40 44 48 149 153 157 161 165 169 173&#39;
        option band &#39;5g&#39;     
        option htmode &#39;VHT40&#39;
        option country &#39;EE&#39;    
        option cell_density &#39;0&#39;
</code></pre><p>Using a manually specified channel has resulted in no Wi-Fi related issues for over half a year.</p>
<p>I consider this a permanent fix.</p>
<p>If you&rsquo;re using a PC and don&rsquo;t want to mess with Wi-Fi issues ever again, then just run some Ethernet cables. It&rsquo;s worth
it.</p>
]]></content:encoded></item><item><title>ThinkPad as a server: third time's the charm</title><link>https://ounapuu.ee/posts/2024/10/16/third-times-the-charm/</link><pubDate>Wed, 16 Oct 2024 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/10/16/third-times-the-charm/</guid><description>Turns out that using stable and performant computers as a home server is way too boring for me.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/10/16/third-times-the-charm/media/cover_hu_89504c7029e38e7c.jpg" width="1200" height="630" alt="ThinkPad as a server: third time's the charm" /><p>This is a follow-up to my two previous attempts on this topic:</p>
<ul>
<li><a href="/posts/2022/05/10/thinkpad-as-a-home-server/">Can a laptop from 2012 be a viable home server?</a></li>
<li><a href="/posts/2023/01/27/thinkpad-as-server-followup/">ThinkPad as a server: the follow-up</a></li>
</ul>
<p>Since then, I&rsquo;ve had quite a few changes to my home server setup:</p>
<ul>
<li><a href="/posts/2023/09/07/ikea-powered-homelab/">I put my home server stuff on an IKEA pegboard</a></li>
<li><a href="/posts/2023/10/09/zimaboard/">I tried the Zimaboard</a></li>
<li><a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">I switched back to the ASRock DeskMini</a></li>
<li><a href="/posts/2024/06/24/back-to-roots/">I got fiber again!</a></li>
</ul>
<p>Zimaboard was
great, <a href="/posts/2023/10/09/zimaboard/#2024-08-20-update">until the CPU became just a little bit too slow for my needs.</a></p>
<p>ASRock Deskmini X300 was great, until I learned that it&rsquo;s actually relatively bad at idle power usage due to lack of
lower sleep states.</p>
<p>Combined with my recent tech cleanup, I am now proudly running all of my services on a single home server, powered by
<a href="/posts/2022/01/09/why-i-went-back-to-using-a-thinkpad-from-2012/">my trusty ThinkPad T430.</a></p>
<p>The promise of USB-C <em>everything</em> was too good to pass up, so I stopped resisting.</p>
<p>Doesn&rsquo;t mean that I won&rsquo;t run hardware into the ground.</p>
<p>Compared to last two attempts, I&rsquo;ve made a couple of important changes to the setup.</p>
<p>There is a weekly <code>tlp recalibrate BAT0</code> job scheduled that completely drains the battery and charges it up again, which
should make sure that the laptop battery survives for a longer time.
The battery charge threshold is set to 80%.</p>
<p>I&rsquo;ve used a knock-off Honeywell PTM7950 thermal pad on the CPU. The cooling performance is comparable to using thermal
paste, but hopefully it doesn&rsquo;t drip out.</p>
<p>The whole setup is mounted to an IKEA pegboard using
a <a href="https://nillkin.org/accessories/nillkin-prodesk-adjustable-laptop-stand">Nillkin ProDesk laptop stand</a>
and a generous amount of zip ties. The combination of zip ties and the rubber feet on the stand result in the stand
barely moving once mounted. The laptop stand itself is very sturdy, and you&rsquo;ll have to use a lot of force to change its
angle.</p>
<p>The CPU uses less power compared to the previous one. The one in the server is
the <a href="https://ark.intel.com/content/www/us/en/ark/products/71670/intel-core-i7-3632qm-processor-6m-cache-up-to-3-20-ghz-bga.html">Intel i7-3632QM</a>,
a quad-core CPU with a 35W TDP.</p>
<p>I still have some scripts running to limit the CPU temperatures to 85°C, just to be on the safe side and avoid
overheating at all costs.</p>









<figure class="center">
  <a href="/posts/2024/10/16/third-times-the-charm/media/setup-1.jpg">
    <img src="/posts/2024/10/16/third-times-the-charm/media/setup-1_hu_6bfa23fe0219b7ab.webp"
     width="1000"
     height="750"
     loading="lazy"
     decoding="async"
     alt="Took me 20 minutes to migrate the server along with the drives, and 2 hours to get the zip tie mounting just right.">

  </a>
  <figcaption class="center">Took me 20 minutes to migrate the server along with the drives, and 2 hours to get the zip tie mounting just right.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2024/10/16/third-times-the-charm/media/setup-2.jpg">
    <img src="/posts/2024/10/16/third-times-the-charm/media/setup-2_hu_f3b73da4eba708e0.webp"
     width="1000"
     height="750"
     loading="lazy"
     decoding="async"
     alt="The small shelf attachment holds two external drives and the power adapter.">

  </a>
  <figcaption class="center">The small shelf attachment holds two external drives and the power adapter.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2024/10/16/third-times-the-charm/media/setup-3.jpg">
    <img src="/posts/2024/10/16/third-times-the-charm/media/setup-3_hu_b808797e960a9df9.webp"
     width="750"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Another angle.">

  </a>
  <figcaption class="center">Another angle.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2024/10/16/third-times-the-charm/media/setup-4.jpg">
    <img src="/posts/2024/10/16/third-times-the-charm/media/setup-4_hu_cb7b9f9356456759.webp"
     width="750"
     height="1000"
     loading="lazy"
     decoding="async"
     alt="Plenty of clearance for adequate cooling.">

  </a>
  <figcaption class="center">Plenty of clearance for adequate cooling.</figcaption>
</figure>

<p>The power consumption is improved on this setup:</p>
<ul>
<li>mean: 27 W</li>
<li>min: 23 W</li>
<li>max: 70 W</li>
</ul>
<p>Results on the DeskMini on a typical day:</p>
<ul>
<li>mean: 34.8 W</li>
<li>min: 28 W</li>
<li>max: 89 W</li>
</ul>
<p>All measurements include the power consumption of the UPS, fiber PON and the router, which is around 10 W.</p>
<p>And the performance is good enough.</p>
<p>I&rsquo;m happy with it.</p>
<p>It&rsquo;s also handy that I now have that one laptop that I can sticker bomb without feeling guilty about removing them later
on.</p>
<h2 id="2025-june-update">
  <a class="heading-anchor" href="#2025-june-update">2025 June update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have been running the ThinkPad T430 as a home server for a long time now. In fact, it&rsquo;s one of the longest stints I&rsquo;ve
had with a specific home server setup. The battery recalibration was <a href="/posts/2025/05/15/home/">temporarily disabled</a>
because of it interfering with UPower configuration that I had in place for shutting down the laptop at a higher battery
percentage (40%), but in all other aspects it&rsquo;s doing fine, and after removing UPower, the battery recalibration works
again.</p>
<p>There was <a href="/posts/2025/06/06/thinkcentre-m900-tiny/">a short week-long experiment with a ThinkCentre M900 Tiny,</a> but
that got put on pause because the USB-connected drives were a bit flaky. The ThinkPad T430 has proven itself to be a
more stable server platform as a result.</p>
]]></content:encoded></item><item><title>My blog successfully survived a scheduled power outage</title><link>https://ounapuu.ee/posts/2024/09/14/look-ma-no-downtime/</link><pubDate>Sat, 14 Sep 2024 11:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/09/14/look-ma-no-downtime/</guid><description>Look, ma, no downtime!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/09/14/look-ma-no-downtime/media/cover_hu_dde5899eab8fc073.jpg" width="1200" height="630" alt="My blog successfully survived a scheduled power outage" /><p>I had the opportunity to test the resiliency of my home server setup due to a scheduled power outage on 2024-09-13.</p>
<p>It was also Friday the 13th. <a href="https://youtu.be/39uoolmtjSA">I&rsquo;m not superstitious, but I&rsquo;m a little stitious.</a></p>
<p>My setup usually consists of the home server, a Wifi AP/router combo box, a converter box for the fiber line, and a
CyberPower UT850EG UPS.</p>
<p>The planned power outage was communicated a week in advance and was supposed to take up to two hours. It ended up taking
about 1 hour 20 minutes.</p>
<p>The CyberPower UPS is good for temporary loss of power and can probably run my whole networking and home server setup
for about 10-15 minutes, which is not enough. Luckily I have one of those Jackery power banks that can provide 230V
output
for a much longer time. During a trial run, I found that this Jackery box can sustain my homelab for about 4 hours
without
any issues.</p>
<p>At 11:02, the power went out and UPS did its thing and kept the setup alive. I then turned on the Jackery power bank,
connected the UPS to the 230 V power line and everything remained operational. I continued working on my laptop
as usual.</p>
<p>My blog and all the other services I run on my home server kept working.</p>









<figure class="center">
  <a href="/posts/2024/09/14/look-ma-no-downtime/media/grafana.png">
    <img src="/posts/2024/09/14/look-ma-no-downtime/media/grafana_hu_17ba41cf1c33bca.webp"
     width="1000"
     height="289"
     loading="lazy"
     decoding="async"
     alt="Great success!">

  </a>
  <figcaption class="center">Great success!</figcaption>
</figure>

<p>I hope to one day do something similar but on a bigger scale, involving solar panels and big batteries. Would be
wicked cool to keep a whole building running off of batteries during outages.</p>
]]></content:encoded></item><item><title>This blog is running on a home server</title><link>https://ounapuu.ee/posts/2024/06/24/back-to-roots/</link><pubDate>Mon, 24 Jun 2024 14:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/06/24/back-to-roots/</guid><description>Yep.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/06/24/back-to-roots/media/cover_hu_73aa3329770b1e79.jpg" width="1200" height="630" alt="This blog is running on a home server" /><p>This blog is running on a home server <a href="/posts/2022/02/09/hn-stats-analytics/">(again).</a></p>
<p>I have once again gained access to a competent internet connection<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, and
I think I have figured out the IPv6 setup as well<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, leading to this change.</p>
<p>The IP address is dynamic, there are occasional power outages and I might just
mess up my configuration and bring it all down, but I get to brag about this
setup so it all balances out.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>it&rsquo;s fiber, baby!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>the software support for IPv6 is a goddamn mess and I regret learning
about it.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>OpenWRT, ISP modem and dynamic IP addresses: how to fix connectivity issues without rebooting your router every time</title><link>https://ounapuu.ee/posts/2024/05/20/openwrt-connectivity-fix/</link><pubDate>Mon, 20 May 2024 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/05/20/openwrt-connectivity-fix/</guid><description>The solution proposed might be a bit specific for my particular setup, but hopefully useful to someone out there.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/05/20/openwrt-connectivity-fix/media/cover_hu_e82e7b9beb9d68f.jpg" width="1200" height="630" alt="OpenWRT, ISP modem and dynamic IP addresses: how to fix connectivity issues without rebooting your router every time" /><p><a href="https://elisa.ee/">My current ISP</a> provides an internet connection over a
copper wire. To use it,
I have a crappy modem (Technicolor CGA2121, DOCSIS 3.0). It&rsquo;s running in bridge
mode,
meaning that all it does is convert the signal running over the coax cable
into plain old Ethernet.</p>
<p>My main networking device is a TP-Link Archer C7 v5. It runs OpenWRT. This
router/Wi-Fi AP box connects to the modem and handles everything, including
getting a public
IPv4 address from the ISP.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>After a power outage or my ISP doing maintenance, the public IP address has
usually changed. This wouldn&rsquo;t be a problem if I just stuck to the ISP-approved
modem.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>With my setup, there was a problem. The OpenWRT box would try to operate with
the IPv4 address that it was
given since the DHCP lease had not yet expired. However, this meant that there
was no internet
connectivity. A reboot of the OpenWRT box would resolve the issue.</p>
<p>This manual workaround wasn&rsquo;t good enough for me. It would be quite problematic
if this issue happened while I was away from home because I&rsquo;d still like to
access
my home server.</p>
<p>After traversing OpenWRT forums and consulting the Slack workspace of my local
hackerspace, I found that bringing up the WAN interface again would result in
the OpenWRT box getting a new public IPv4 address. Problem solved!</p>
<p>To automate this workaround, I created a single crontab entry in the OpenWRT
box. This is
also configurable in a graphical user interface as long as you
have <a href="https://openwrt.org/docs/guide-user/luci/start">LuCI installed.</a></p>
<p>The crontab entry looks like this:</p>
<p><code>*/5 * * * * /bin/ash -c '/bin/ping -c 3 8.8.8.8 &gt; /dev/null || /sbin/ifup wan'</code></p>
<p>Every 5 minutes, the router pings Google&rsquo;s DNS server. If that command succeeds,
then the internet connection works and that&rsquo;s it. If the ping fails, then the
other half of the shell command is executed, which brings up the <code>wan</code> interface
on my router.</p>
<p>Feel free to use a different IP address to test with. Your WAN network interface
might also have a different name.</p>
<p>The downside of this solution is that if the server you&rsquo;re using to verify your
internet connection is down or refuses pings, then you&rsquo;ll be causing
interruptions in your home network every 5 minutes.</p>
<p>Talking to the ISP about this issue was something I considered as well. Then
I remembered that it took me 1.5 months of fighting chatbots and repeating the
same information to different customer care agents to use my own modem that&rsquo;s
identical to the one the ISP uses. That&rsquo;s a <em>hell no</em> from me.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I really should get around to drilling those holes in the apartment
building to get access to a fiber connection.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>using the ISP-approved box would introduce a whole other set of problems
because they are surprisingly low quality.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Monitoring energy usage with smart plugs, Prometheus and Grafana</title><link>https://ounapuu.ee/posts/2024/05/02/smartplugs/</link><pubDate>Thu, 02 May 2024 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2024/05/02/smartplugs/</guid><description>My obsession with measuring the power consumption of my devices reached a whole new level.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2024/05/02/smartplugs/media/cover_hu_1ceb39d1f5a6c2e9.jpg" width="1200" height="630" alt="Monitoring energy usage with smart plugs, Prometheus and Grafana" /><p>This post <strong>isn&rsquo;t</strong> a detailed line-by-line tutorial on how to set up each individual piece of the setup as those types of
guides tend to get out of date really easily, but if you know your way around Linux and the command line, then you can
definitely replicate this setup on your own.</p>
<p>Over the past few years I&rsquo;ve been interested in learning about how much energy my computing setup and home
appliances use.
I&rsquo;ve used a simple digital energy meter before to get instantaneous readings, but that was not ideal for monitoring
how an electrical appliance consumes power over a longer time period.</p>
<p>My friend bought a few smart plugs from <a href="https://www.athom.tech/">athom.tech</a>. After getting confirmation
that they don&rsquo;t suck, I went ahead and ordered some myself.</p>
<p>The smart plugs I bought were the <code>EU style plug V3</code> variant. The shipping times in EU were reasonably fast, shipping in 9
days (and that included Christmas!).</p>
<p>The plugs ship with <a href="https://tasmota.github.io/docs/">Tasmota</a> pre-flashed. The plugs come with a small paper strip explaining
the steps to take to connect the plug to your Wi-Fi network, and after that you can manage the plug in your browser.</p>









<figure class="center">
  <a href="/posts/2024/05/02/smartplugs/media/tasmota-quick-start.jpg">
    <img src="/posts/2024/05/02/smartplugs/media/tasmota-quick-start_hu_a32ff56422f86b3b.webp"
     width="1280"
     height="502"
     loading="lazy"
     decoding="async"
     alt="Quick start instructions that ship with the smart plug.">

  </a>
  <figcaption class="center">Quick start instructions that ship with the smart plug.</figcaption>
</figure>

<p>Updating the firmware to the latest version is easy and doable in the web GUI with just a few clicks.</p>









<figure class="center">
  <a href="/posts/2024/05/02/smartplugs/media/webui.png">
    <img src="/posts/2024/05/02/smartplugs/media/webui_hu_56745710490202cf.webp"
     width="395"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The web UI is simple and very functional.">

  </a>
  <figcaption class="center">The web UI is simple and very functional.</figcaption>
</figure>

<h2 id="the-software-stack">
  <a class="heading-anchor" href="#the-software-stack">The software stack<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My initial goal with these plugs was to visually monitor the power consumption of a few devices, such as my home server, router,
workstation setup and the electric water heater.</p>
<p>The power meter data is collected to an existing <a href="https://prometheus.io/">Prometheus</a> instance on my home server.
If you&rsquo;re not sure what Prometheus is, then think of it as a tool that periodically reads metrics from different
sources, saves them to disk and allows you to later query and manipulate that information.</p>
<p>I run multiple instances of this <a href="https://github.com/astr0n8t/tasmota-power-exporter">tasmota-power-exporter</a> solution on my server, one per plug, which get scraped once
per second by the Prometheus instance. <a href="https://github.com/arendst/Tasmota/issues/9206">It is possible to also make the plugs themselves export these metrics,</a>
but I didn&rsquo;t fancy building Tasmota firmware myself, yet.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>I already had a <a href="https://grafana.com/">Grafana</a> instance running on my home server, so I reused that to show a few basic
graphs for the power meter setup.</p>
<p><em>Free tech tip</em>: make sure to change the <code>min step</code> setting to 1 second to get the most detailed data points on your graphs.</p>









<figure class="center">
  <a href="/posts/2024/05/02/smartplugs/media/grafana-minstep.png">
    <img src="/posts/2024/05/02/smartplugs/media/grafana-minstep_hu_eca401c841351ce8.webp"
     width="550"
     height="317"
     loading="lazy"
     decoding="async"
     alt="It&#39;s this one. ">

  </a>
  <figcaption class="center">It&#39;s this one. </figcaption>
</figure>

<h2 id="observations-and-findings">
  <a class="heading-anchor" href="#observations-and-findings">Observations and findings<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>So, what have I learned after running this setup for almost 4 months?</p>
<h3 id="water-heater">
  <a class="heading-anchor" href="#water-heater">Water heater<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>It shouldn&rsquo;t come as a surprise that the electric water heater uses up the most power. The one we have is a 30L one,
just enough for a quick shower or two or for washing a large load of dishes.</p>
<p>Typical power usage: 4.51 kWh/day.</p>
<p>Minimum observed: 0.56 kWh/day, happens usually when nobody is at home</p>
<p>Maximum observed: 11.1 kWh/day, a lot of washing and showering happened on that day</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/boiler-graph.png">
    <img src="/posts/2024/05/02/smartplugs/media/boiler-graph_hu_2a8c28d3af743eba.webp"
     width="1120"
     height="475"
     loading="lazy"
     decoding="async"
     alt="Typical power consumption pattern of a water heater.">

  </a>
  <figcaption class="center">Typical power consumption pattern of a water heater.</figcaption>
</figure>

<h3 id="home-server-setup">
  <a class="heading-anchor" href="#home-server-setup">Home server setup<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>I run all my home server workloads off of a <a href="/posts/2023/10/09/zimaboard/">Zimaboard</a>. One of its big selling
points for me was its super low power consumption.
When idling, the Zimaboard can use about 2 W, typical power usage with all my services running was about 7 W and the
maximum power consumption was around 15 W.</p>
<p>The Zimaboard was actually using <em>less power</em> than my internet modem/router box (which is hot garbage by the way).
The ISP-provided box used 12-14 W at all times, regardless if it was operating in router or bridge mode.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/zimaboard-graph.png">
    <img src="/posts/2024/05/02/smartplugs/media/zimaboard-graph_hu_c8343b4afdf7d1d8.webp"
     width="1120"
     height="475"
     loading="lazy"
     decoding="async"
     alt="Zimaboard &#43; modem/router box power consumption.">

  </a>
  <figcaption class="center">Zimaboard &#43; modem/router box power consumption.</figcaption>
</figure>










<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/isp-box-graph.png">
    <img src="/posts/2024/05/02/smartplugs/media/isp-box-graph_hu_608b69787ca51534.webp"
     width="1120"
     height="475"
     loading="lazy"
     decoding="async"
     alt="The ISP modem/router box is a horribly inefficient device for what it does.">

  </a>
  <figcaption class="center">The ISP modem/router box is a horribly inefficient device for what it does.</figcaption>
</figure>

<p>At one point I temporarily switched my home server setup back to <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">the ASRock Deskmini X300</a>,
mainly because I added some latency-sensitive workloads onto my home server setup and the Zimaboard was a bit too weak
for those.</p>
<p>One thing that became really obvious from the power meter is that the Deskmini idle power consumption is
horrible in comparison to the Zimaboard, coming in at around 15-20 W. This might be in part because my Deskmini doesn&rsquo;t
seem to expose any lower CPU power states than C3 while the Zimaboard exposed C-states all the way down to C10. I could not
find a way to expose lower C-states in UEFI settings or the Linux kernel. Based on a quick remark in <a href="https://www.youtube.com/watch?v=J_WJI4hp_B8">this video</a> I believe that it should
be possible to drop ASRock a message and receive a custom BIOS that enables some extra features, but that seems even
more unlikely for a consumer-grade device such as this one.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/deskmini-graph.png">
    <img src="/posts/2024/05/02/smartplugs/media/deskmini-graph_hu_6e08750be9fec2.webp"
     width="1120"
     height="475"
     loading="lazy"
     decoding="async"
     alt="ASRock Deskmini X300 &#43; ISP box power consumption.">

  </a>
  <figcaption class="center">ASRock Deskmini X300 &#43; ISP box power consumption.</figcaption>
</figure>

<p>I&rsquo;ve added a panel to my usual Prometheus node exporter Grafana view that shows the server setup power consumption alongside
other metrics. Higher CPU activity is clearly visible on the power consumption graphs.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/cpu-power-correlation.png">
    <img src="/posts/2024/05/02/smartplugs/media/cpu-power-correlation_hu_6883771b31c2a56.webp"
     width="1280"
     height="397"
     loading="lazy"
     decoding="async"
     alt="A moderate jump in CPU usage can result in a big jump in power consumption.">

  </a>
  <figcaption class="center">A moderate jump in CPU usage can result in a big jump in power consumption.</figcaption>
</figure>

<h3 id="voltage">
  <a class="heading-anchor" href="#voltage">Voltage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>The Tasmota plugs also report current voltage values. I graphed them just for fun, but noticed that there is a sort of
seasonality to the values. During the usual peak power consumption hours the voltage drops across the board.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/voltage-seasonality.png">
    <img src="/posts/2024/05/02/smartplugs/media/voltage-seasonality_hu_21ee4babcb7c3385.webp"
     width="1280"
     height="404"
     loading="lazy"
     decoding="async"
     alt="Seasonality as expressed through voltage readings.">

  </a>
  <figcaption class="center">Seasonality as expressed through voltage readings.</figcaption>
</figure>

<p>This seems like a candidate for testing anomaly detection, as shown in <a href="https://about.gitlab.com/blog/2019/07/23/anomaly-detection-using-prometheus/">this great GitLab article.</a>
I&rsquo;ve used this concept at work and it works reasonably well for some metrics.</p>
<p>In other cases the voltage drops were caused by running appliances that use a lot of power, such as the water heater, electric kettle, electric stove or the microwave.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/voltage-correlation.png">
    <img src="/posts/2024/05/02/smartplugs/media/voltage-correlation_hu_7815ab709ab90ee5.webp"
     width="1280"
     height="640"
     loading="lazy"
     decoding="async"
     alt="Water heater causing the voltage to drop slightly for all plugs.">

  </a>
  <figcaption class="center">Water heater causing the voltage to drop slightly for all plugs.</figcaption>
</figure>

<p>During cooking with an electric stove, the on-off cycles were also noticeable on
the voltage reading on all of the plugs.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/voltage-cooking.png">
    <img src="/posts/2024/05/02/smartplugs/media/voltage-cooking_hu_bb3303151c1e2b9c.webp"
     width="1277"
     height="483"
     loading="lazy"
     decoding="async"
     alt="The impact of an electric stove on the voltage.">

  </a>
  <figcaption class="center">The impact of an electric stove on the voltage.</figcaption>
</figure>

<h3 id="workstation">
  <a class="heading-anchor" href="#workstation">Workstation<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>I have one plug that reports numbers for everything that&rsquo;s connected to my home office setup: monitor, USB-C dock,
monitor light bar and anything that might be charging on the table.</p>
<p>The power consumption of this setup varies a lot. Sometimes I do a longer home office stint. Sometimes I recharge various
devices.</p>
<p>The typical power consumption of the whole setup while doing something on my computer is around 45-60 W, with peaks near
90-110 W. For an ultrawide monitor, USB-C dock and my laptop I think this is a pretty good result. I&rsquo;ve had desktop PC-s
that have used just as much power at idle, and in the olden days there were incandescent light bulbs that used up more
electricity than this!</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/workstation-graph.png">
    <img src="/posts/2024/05/02/smartplugs/media/workstation-graph_hu_baa39b967d92af97.webp"
     width="1280"
     height="474"
     loading="lazy"
     decoding="async"
     alt="Typical power consumption of my work desk when working from home.">

  </a>
  <figcaption class="center">Typical power consumption of my work desk when working from home.</figcaption>
</figure>

<p>Typical power usage: 0.95 kWh/day.</p>
<p>Minimum observed: 0.07 kWh/day</p>
<p>Maximum observed: 1.52 kWh/day</p>
<h3 id="charging">
  <a class="heading-anchor" href="#charging">Charging<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>These plugs are also great for observing the charging patterns of various devices.</p>
<p>A laptop or a power bank charges faster at the beginning, but the speed drops off as the battery gets more full.
At one point trickle charging seems to kick in until the device is fully charged.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/charging-powerbank.png">
    <img src="/posts/2024/05/02/smartplugs/media/charging-powerbank_hu_62e637cb8024eed0.webp"
     width="1279"
     height="530"
     loading="lazy"
     decoding="async"
     alt="A power bank charges quickly in the beginning and starts slowing down once it gets close to being fully charged.">

  </a>
  <figcaption class="center">A power bank charges quickly in the beginning and starts slowing down once it gets close to being fully charged.</figcaption>
</figure>

<p>This pattern is similar on most devices that I charge. The battery on my e-bike seems to be an exception to the rule,
with a slighly increasing power consumption throughout, and a faster drop at the end of the charging cycle.</p>









<figure class="left">
  <a href="/posts/2024/05/02/smartplugs/media/charging-ebike-battery.png">
    <img src="/posts/2024/05/02/smartplugs/media/charging-ebike-battery_hu_dbfbc4ce58dac808.webp"
     width="1279"
     height="530"
     loading="lazy"
     decoding="async"
     alt="E-bike battery charging pattern, from nearly empty to full.">

  </a>
  <figcaption class="center">E-bike battery charging pattern, from nearly empty to full.</figcaption>
</figure>

<p>0.5kWh of power consumed for 60km of range with the &ldquo;Turbo&rdquo; preset on the bike doesn&rsquo;t sound bad at all. Half a cent per
kilometer!</p>
<h3 id="stability">
  <a class="heading-anchor" href="#stability">Stability<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>The stability of the smart plugs is usually fine, but there are frequent cases where certain plugs don&rsquo;t report back in time
with the statistics. This may be a Wi-Fi access point issue, but annoying nevertheless.</p>
<p>I&rsquo;ve had to completely power cycle two plugs a few times because they dropped off from the network completely and would
not come back. Again, could be the fault of my Wi-Fi AP.</p>
<h3 id="future-ideas">
  <a class="heading-anchor" href="#future-ideas">Future ideas<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>The plugs also provide a way to turn the devices on and off over different
API-s (even over HTTP!), which is something I&rsquo;d like to utilize either using something like <a href="https://www.home-assistant.io/">Home Assistant</a>, or a simple
script that toggles certain devices on and off based on the current electricity price.</p>
<p>I haven&rsquo;t gotten around to this part yet, but from my research it seems that <a href="https://github.com/custom-components/nordpool">the necessary integrations
exist for Home Assistant.</a></p>
<h2 id="closing-thoughts">
  <a class="heading-anchor" href="#closing-thoughts">Closing thoughts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Overall, I&rsquo;m very happy with this setup. I can get reliable measurements for all sorts of computing setups from now on,
which will make judging the power efficiency of the devices I use much easier. No more guesswork!</p>
<p>If you enjoyed this post, then I highly recommend giving <a href="https://fosdem.org/2024/schedule/event/fosdem-2024-2723-power-profiling-my-entire-house-with-the-firefox-profiler/">this FOSDEM 2024 talk by Florian Quèze a listen.</a>
The talk also goes into details about measuring the power consumption of various devices in the speakers&rsquo; home and
observations that they&rsquo;ve made.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This was pointed out to me by a fellow reader. Thank you!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>The optimization treadmill: why I keep changing my computing setup all the time</title><link>https://ounapuu.ee/posts/2023/10/25/the-optimization-treadmill/</link><pubDate>Wed, 25 Oct 2023 10:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/10/25/the-optimization-treadmill/</guid><description>A short explanation about what drives me to experiment with new hardware setups in my self-hosting hobby.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/10/25/the-optimization-treadmill/media/cover_hu_8818061f304a9396.jpg" width="1200" height="630" alt="The optimization treadmill: why I keep changing my computing setup all the time" /><p>I have a bad habit of changing my computing setups all the time. I tend to see new gear, then I get
some new ideas, and then I obsessively think about it for weeks and months until I just buy it.
And then the cycle repeats.</p>
<p>I&rsquo;ve had time to think about why that keeps happening and I think I&rsquo;ve got it.</p>
<p><em><strong>I keep changing the goals, constantly,</strong></em> and with that I kept optimizing my
setup in a different direction every time.</p>
<p>This post also serves as a way to explain <a href="/posts/2023/10/09/zimaboard/">my thought process behind my last post about the Zimaboard</a>,
since my writing may not have been clear enough on that point, or some of you just can&rsquo;t read.</p>
<h2 id="the-treadmill">
  <a class="heading-anchor" href="#the-treadmill">The treadmill<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It all started with the first step in my self-hosting adventure. I had a 1TB WD external hard drive that was a single copy
of all my important files, which is less than ideal if you want to preserve your data.
My goal became to have another redundant copy of the storage, so I built a server from old PC parts and
used hard drives, all running ZFS, and hosted in a room where loud PC-s were more of a norm.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-1.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-1_hu_25c122b165ff26a8.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="First actual server setup that I had.">

  </a>
  <figcaption class="center">First actual server setup that I had.</figcaption>
</figure>

<p>After that setup moved to my rented apartment, I discovered that having a buzzing tower of 8 hard drives
(that was an upgrade I later made) consumes
a lot of power and is also unbearable when you&rsquo;re trying to sleep in the same room.
My goal became to reduce the noise and the power consumption, so I upgraded to a Ryzen 2000-series based setup
and at least two WD Red 4TB hard drives. It was quieter, faster and more power efficient compared to the previous setup.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-2.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-2_hu_5657a28acdf54d9.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Fun fact: one of the WD Red drives died and had to be replaced through warranty. ">

  </a>
  <figcaption class="center">Fun fact: one of the WD Red drives died and had to be replaced through warranty. </figcaption>
</figure>

<p>Then I discovered that laptops use even less power than that. A ThinkPad X230 I had around used less than 10 watts
when idling, and it just so happened that I had one to play around with.
My goal became to reduce the power consumption of my home server setup even more.
I ended up putting my storage on two
4TB WD Red hard drives connected over USB 3.0 and running my home services off of that ThinkPad.</p>
<p>Soon after that, I discovered that having a cat around USB-connected storage running <code>btrfs</code> is a really bad idea.
There was data loss, but luckily nothing I could not replace. My goal became to have a low power setup that was more
cat-proof and did not rely on USB-based storage. That&rsquo;s how I ended up with a TerraMaster F2-221.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-3.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-3_hu_7a22da10ddae38cf.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Meet Tux, the data loss queen. Hopefully makes up for the fact that I don&#39;t have a 
picture of those two setups.  ">

  </a>
  <figcaption class="center">Meet Tux, the data loss queen. Hopefully makes up for the fact that I don&#39;t have a 
picture of those two setups.  </figcaption>
</figure>

<p>Damn, these hard drives sure are loud in that NAS! I also discovered that some external 2.5&quot; hard drive enclosures
can be opened up to reveal 2.5&quot; 15mm SATA hard drives in up to 5TB capacities.
<a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/">And you can plop those onto a PCIe card, for some reason.</a>
And I really liked the Thermaltake Core V1 and SSD-s for certain types of storage.
My goal became to build a really cool and performant server that housed both hard drives and SSD-s, because why not?</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-4.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-4_hu_6a6e46bf345af9ea.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="RGB-powered server.  ">

  </a>
  <figcaption class="center">RGB-powered server.  </figcaption>
</figure>

<p>Oh, wait, no, that thing uses a lot of power and a ThinkPad T430 became available in my computing fleet.
I probably got a good deal on some 8TB hard drives around this time as well.
My goal became having a lot of storage around while also using less power, and having it all
as cat-proof as possible. That&rsquo;s how a ThinkPad T430 ended up being a home server.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-5.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-5_hu_7e083d43ceb10ec.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Embrace the jank.">

  </a>
  <figcaption class="center">Embrace the jank.</figcaption>
</figure>

<p>Oh, crap, that ThinkPad kept overheating because the CPU in it was a bit too much at higher loads!
My goal became to find a suitable replacement that did not use a lot of power.
Luckily I heard about the concept of <a href="https://www.servethehome.com/introducing-project-tinyminimicro-home-lab-revolution/">TinyMiniMicro</a>
and got myself a Lenovo ThinkCentre M73 Tiny.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-6.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-6_hu_e5e6ff1adfec4343.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The original TinyMiniMicro setup. ">

  </a>
  <figcaption class="center">The original TinyMiniMicro setup. </figcaption>
</figure>

<p>Damn, those hard drives sure are noisy, apparently due to WD running those at 7200rpm.
My goal became to silence those hard drives as much as possible. I got a lot of acoustic foam, and what ended up working
was to stack the drives horizontally, and add some foam between the pieces, that got rid of the humming. I also
added a fan to keep the drives from overheating.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-7.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-7_hu_4f0d8b9faae28e72.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The TinyMiniMicro setup with some foam. I added the fan later. ">

  </a>
  <figcaption class="center">The TinyMiniMicro setup with some foam. I added the fan later. </figcaption>
</figure>

<p>Hold on, the Raspberry Pi 4 is allegedly usable as a home server now? And it uses even less power when idling?
My goal then became to have a server setup that has a single-digit idle power consumption, meaning less than 10 watts.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-8.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-8_hu_b0ee93544c6e437a.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The Raspberry Pi 4 that I did testing with. ">

  </a>
  <figcaption class="center">The Raspberry Pi 4 that I did testing with. </figcaption>
</figure>

<p>Unfortunately I could not get the software part running right, the setup would freeze due to unknown reasons. At least
<a href="/posts/2021/02/01/how-to-fix-zfs-pool-not-importing-at-boot/">I wrote a post about troubleshooting ZFS issues</a>
as part of this run, and Google keeps recommending it to people according to Google Search Console data.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/screenshot-google.png">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/screenshot-google_hu_241a457ed5f6ce17.webp"
     width="933"
     height="800"
     loading="lazy"
     decoding="async"
     alt="If Google keeps recommending it, then I guess it&#39;s useful to people. ">

  </a>
  <figcaption class="center">If Google keeps recommending it, then I guess it&#39;s useful to people. </figcaption>
</figure>

<p>Alright, I can&rsquo;t make the setup more efficient. Hold on, I also have a desktop PC, and that also consumes power when
idling. That seems wasteful. My goal became to do my computing all on one machine, filling the roles of a server,
workstation and gaming PC all at the same time. <a href="/posts/2021/05/23/self-hosting-endgame/">And I did it, and wrote a post about it as well!</a></p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-9.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-9_hu_3ea578e613d1eec1.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The all-in-one setup. ">

  </a>
  <figcaption class="center">The all-in-one setup. </figcaption>
</figure>

<p>Spoiler alert: it was in fact <em>not</em> the end-game of my setup, because I soon discovered that having everything on the
same PC requires quite a special setup, and a reboot on the host OS affects all the other use cases. If you care about
uptime, then it&rsquo;s probably better to have separate machines for all of that. I didn&rsquo;t want to give up on the idea of virtualized
setups just yet, and thus my goal became to have one PC for my server and gaming needs. Games need storage, lots of it.
My server has lots of storage. Makes sense, right?</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-10.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-10_hu_96cab6cd6b670713.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The heart of the new setup: ASRock X570M Pro4 motherboard.  ">

  </a>
  <figcaption class="center">The heart of the new setup: ASRock X570M Pro4 motherboard.  </figcaption>
</figure>

<p>After using that setup, <a href="/posts/2021/12/29/vr-vfio-latency/">I discovered that VR and virtualized gaming don&rsquo;t mix that well.</a>
Damnit. Oh, hey, I have all these SSD-s now from that experiment, and if I shrink my data needs a bit, I could
fit it all on a mirrored setup of two 4TB SSD-s, and they don&rsquo;t use much power as well. That opened up a
lot of possibilities regarding my next setup because a lot of small PC-s can handle two SATA SSD-s just fine.
My goal became to build a silent and efficient home server. <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">This resulted in the ASRock Deskmini X300 setup.</a></p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-11.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-11_hu_240437cee7dcdc08.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Look how tiny it is!">

  </a>
  <figcaption class="center">Look how tiny it is!</figcaption>
</figure>

<blockquote>
<p>I’m hoping that the current DeskMini-based server configuration is the one that will last me a while.</p>
</blockquote>
<p>That aged well.</p>
<p>I had a ThinkPad T430 lying around, and now that my storage needs were served by two 4TB SSD-s, I could
finally do that <a href="/posts/2020/08/22/stupid-project-ideas-1/">one stupid idea from 2020</a>.
I also dislike knowing that I have perfectly good hardware sitting in a box and collecting dust.
My goal then became to use
my ThinkPad T430 as a low-power, silent and efficient home server.
<a href="/posts/2022/05/10/thinkpad-as-a-home-server/">It was successful.</a>
<a href="/posts/2023/01/27/thinkpad-as-server-followup/">Or at least mostly successful.</a></p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-12.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-12_hu_60bcdba190871e52.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The ThinkPad T430 as a server.">

  </a>
  <figcaption class="center">The ThinkPad T430 as a server.</figcaption>
</figure>

<p>But the search for that elusive combination of low power consumption, adequate performance, stability, resilience and silence
was not over. My blog gained traction from time to time and it would be really embarrassing if an overheated
laptop or a longer power outage resulted in an outage. You see, the ThinkPad was good as a server, but it
still overheated under specific conditions and once the battery runs out, the &ldquo;Power on with AC attach&rdquo; functionality
does not work, which is quite bad for a server. My goal became to find that elusive solution.</p>
<p>I tried the LattePanda V1 since I got it for a good price. <a href="/posts/2023/02/28/lattepanda-v1/">Didn&rsquo;t work out for my use case, sadly.</a>
The website situation got solved with moving that portion of my
self-hosting setup to <a href="/posts/2023/03/26/hosted-on-kspace/">k-space hosting</a>, leaving me to do further experiments
without affecting my lovely website that much.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-13.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-13_hu_fce367b478e69d94.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The LattePanda test setup.">

  </a>
  <figcaption class="center">The LattePanda test setup.</figcaption>
</figure>

<p>After keeping my eyes open for various options, <a href="/posts/2023/10/09/zimaboard/">the Zimaboard was the one that finally won.</a>
Silent. Meets my storage, networking and performance requirements. Small. Super low power usage. x86 based so I know my stuff
runs on it well. It&rsquo;s not perfect, but it did all of those things.</p>









<figure class="center">
  <a href="/posts/2023/10/25/the-optimization-treadmill/media/setup-14.jpg">
    <img src="/posts/2023/10/25/the-optimization-treadmill/media/setup-14_hu_263feac6bc54aaa1.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Hopefully this one sticks.">

  </a>
  <figcaption class="center">Hopefully this one sticks.</figcaption>
</figure>

<p>And there you have it, the reason why I have written over half of these blog posts, and why my setup just keeps changing
and depleting my wallet at the same time.</p>
<p>Let&rsquo;s be honest, I&rsquo;m sure that as soon as I find something
exciting in the tech world to play around with, I&rsquo;m probably going to try it out. Some call it <em>passion</em>, I call it
<em>lack of fiscal responsibility</em>.</p>
<p><em><strong>Free tech tip</strong></em> to those starting out in self-hosting: experimentation
is really fun, but it&rsquo;s easy to lose focus and get carried
away with changing your setup all the time. You can do a lot with much less
hardware than you think, so try to approach building a minimum viable home server
setup first and upgrade only if absolutely necessary. In my experience it&rsquo;s just as fun
and probably much cheaper as well.</p>
]]></content:encoded></item><item><title>Zimaboard: the closest thing to my dream home server setup</title><link>https://ounapuu.ee/posts/2023/10/09/zimaboard/</link><pubDate>Mon, 09 Oct 2023 14:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/10/09/zimaboard/</guid><description>I gave in to my impulses and bought myself a small single board computer to be my power-efficient home server, here's how it went.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/10/09/zimaboard/media/cover_hu_1511165ed98ee92c.jpg" width="1200" height="630" alt="Zimaboard: the closest thing to my dream home server setup" /><p>I stumbled upon <a href="https://youtu.be/V_ZdvrIMKEQ">this Hardware Haven video about the Zimaboard recently.</a></p>
<p>I liked it a lot.</p>
<p>I finally bought one.</p>
<p>In short, <a href="https://www.zimaboard.com/zimaboard/product">Zimaboard</a> is a small single-board computer that is relatively affordable and comes
with an interesting selection of ports, which includes an exposed PCI Express port.</p>
<p>Before we get down to the build, here&rsquo;s a list of aspects that I want to see in my dream home server:</p>
<ul>
<li>low power usage (2-15W typical power usage)</li>
<li>8GB of RAM or better</li>
<li>enough performance to run my workloads, most of which are containerized</li>
<li>2x SATA or NVMe SSD slots, plus option for a third drive for the OS</li>
<li>passively cooled and completely silent</li>
<li>compact size</li>
<li>gigabit Ethernet or better</li>
</ul>
<p>You might be thinking, &ldquo;<em>Wait, that&rsquo;s your <strong>dream setup</strong>? No clusters of machines, Threadrippers, 10 Gigabit networking, crazy number of disks?</em>&rdquo;.
Well, yes. After years of trying all sorts of setups and learning about my home server usage patterns, this is the set of requirements that finds a balance between performance, efficiency
and silence.</p>
<h2 id="basics">
  <a class="heading-anchor" href="#basics">Basics<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I recommend checking <a href="https://www.zimaboard.com/zimaboard/product">the product page</a> to see the exact specifications.
The configuration I bought was the 832 model: 8GB of RAM, 32GB of eMMC storage and a quad-core Intel Celeron N3450 CPU.
It&rsquo;s not the most powerful setup or even a recent one with the CPU being from 2016, but it&rsquo;s just powerful enough to fit
my needs.</p>
<p>This variant of the board costs 200 USD, but other configurations cost much less
than that, I just needed the extra memory to be on the safe side. If you don&rsquo;t
care about the noise and size aspect of home servers, then you can get a better
deal on the used market (<a href="https://www.servethehome.com/introducing-project-tinyminimicro-home-lab-revolution/">see the TinyMiniMicro project for inspiration)</a>,
but as you know by this point, I care about those aspects a lot.</p>
<h2 id="the-package">
  <a class="heading-anchor" href="#the-package">The package<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>What sets the Zimaboard apart from other single board computers is how polished the product feels.
Unlike a board like the Raspberry Pi, this one comes with a case and a cooling setup
already attached to it. I suspect that a similarily configured Raspberry Pi 4/5
with all the accessories added on top would result in a price that&rsquo;s quite
similar to the cost of a top-of-the-line Zimaboard.</p>
<p>The heatsink looks great and is practical at the same time.
Under the most torturous loads I could only see the CPU being around 72°C and due
to it being passively cooled it made absolutely no noise. With the case being
present, I do not have to worry about placing the board on my desk and scratching
the table or shorting something out.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/theboard.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/theboard_hu_2cd89bb8686bd5dc.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Just plop it wherever.">

  </a>
  <figcaption class="center">Just plop it wherever.</figcaption>
</figure>

<p>The board does not seem to have a power button, but by default it&rsquo;s configured
to power on as soon as you connect the power supply, which is great if you&rsquo;re
going to use this as a home server.</p>
<p>The box that the board was shipped survived and overall I&rsquo;d say that the packaging
is good. The board comes with some stickers and a single SATA data+power cable.
The included power adapter comes with EU, US and UK plugs all included.</p>
<p>Shipping to Estonia was quite fast, taking just 10 days. The shipping costs were
18 USD.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/box.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/box_hu_eb50fa4af959b977.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The box did its job.">

  </a>
  <figcaption class="center">The box did its job.</figcaption>
</figure>

<h2 id="storage">
  <a class="heading-anchor" href="#storage">Storage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The included 32GB eMMC storage is fine for hosting your operating system. The
read speeds cap out at around 175 MB/s and the typical write speeds I observed
were around 50-100 MB/s. The storage is identified as <code>mmc-BJTD4R_0xc7d04e40</code> under
<code>/dev/disk/by-id/</code>, and searching online suggests that it&rsquo;s a Samsung chip.</p>
<p>Because this board offers two SATA ports, I also added a SATA Y-cable to my order
(4 USD) so that I can take my existing Samsung 870 QVO 4TB SATA drives and move
my home server setup to this board.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/ycable.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/ycable_hu_1b434f16b568b5da.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="SATA Y-cable in action.">

  </a>
  <figcaption class="center">SATA Y-cable in action.</figcaption>
</figure>

<p>Allegedly this cable can also be used to drive
two 3.5&quot; hard drives powered by the board itself according to <a href="https://shop.zimaboard.com/products/sata-y-cable-for-zimaboard-2-5-inch-hdd-3-5-inch-hdd-raid-free-nas-unraid">the shop page
for the Y-cable</a>, but I suspect that at that point you&rsquo;ll be pushing the limits of
the 12V/3A power adapter.</p>
<p>There is also a white drive activity LED
placed near the SATA power connector on the board. Perhaps not for everyone, but I
like the aesthetic and the sight of the server doing server things.</p>
<p>The performance of the SATA ports is what you would expect. When performing
read operations on both SSD-s I saw the maximum total transfer rates hover around
900-950MB/s, which is pretty close to the SATA III transfer speed limit.</p>
<p>There is no native way to mount the two SATA drives to the Zimaboard. The creators
of the board do sell a metal bracket, but it doesn&rsquo;t seem to integrate that well
to the board. However, <a href="https://www.printables.com/model/224057-zimaboard-dual-hdd-stand">there exists a 3D printable design that houses two
2.5&quot; drives, even 15mm ones</a>, and
that&rsquo;s how I ended up using a 3D printer for the first time in my life.
The print was done using a <a href="https://wiki.k-space.ee/en/utilities/3D-Printer">Voron v2 Afterburner printer hosted at k-space</a>
and it came out pretty well.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/3dprint-1.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/3dprint-1_hu_1063ec1f0205a475.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Print in progress.">

  </a>
  <figcaption class="center">Print in progress.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/3dprint-2.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/3dprint-2_hu_d701924b7455a796.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The final product">

  </a>
  <figcaption class="center">The final product</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/3dprint-3.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/3dprint-3_hu_824404626ee747d8.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Another angle.">

  </a>
  <figcaption class="center">Another angle.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/3dprint-4.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/3dprint-4_hu_734e2439b5176454.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Some 3D printing related inconsistencies, but nothing serious.">

  </a>
  <figcaption class="center">Some 3D printing related inconsistencies, but nothing serious.</figcaption>
</figure>

<p>The SSD mounting holes were a bit finicky due
to slight printing errors, and during my first installation attempt I forgot to
put in the plastic middle layer of the case that&rsquo;s between the PCB and the stock
bottom cover, but other than that the installation was a breeze.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/board-backside.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/board-backside_hu_df793b4541493c33.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Installation of the caddy requires removing the stock backplate and splitting it.">

  </a>
  <figcaption class="center">Installation of the caddy requires removing the stock backplate and splitting it.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-1.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-1_hu_78d2b684b7f1572c.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The finished result.">

  </a>
  <figcaption class="center">The finished result.</figcaption>
</figure>

<p>








<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-2.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-2_hu_bb144d2c394a571f.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-3.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-3_hu_835bdd7977c2313d.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-4.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-4_hu_bcbdbc57030a3901.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-5.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-5_hu_7ba9351ed37ad4e3.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-6.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-6_hu_5a82ffd61f02dfe2.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/caddy-7.jpg" aria-label="View full-size image">
    <img src="/posts/2023/10/09/zimaboard/media/caddy-7_hu_4e393891551319ac.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>
</p>
<p>The drives never hit above 64°C, which is absolutely okay for these SSD-s. I&rsquo;m not
sure how actual spinning hard drives might fare in this environment, but I don&rsquo;t
think that it&rsquo;s going to be that serious because 2.5&quot; hard drives should not
generate as much heat in the first place.</p>
<h2 id="power-consumption">
  <a class="heading-anchor" href="#power-consumption">Power consumption<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>What I love about this board is the power usage. At this point my home server
is not even the most power hungry component of my setup, that honor now goes
to the ISP-provided router/modem combo box that always draws at least 12W, even
when it&rsquo;s in bridge mode.</p>
<p>Here are my power usage measurements (measured with a simple power meter):</p>
<ul>
<li>idle: 2.5W</li>
<li>no drives attached, CPU stress test (<code>stress -c 4</code>): 9.0W</li>
<li>one Samsung 870 QVO 4TB SSD attached, CPU stress test: 13.2W</li>
<li>2 SSD-s attached, typical power draw in my setup (~10-40% CPU usage): ~8-9W</li>
<li>2 SSD-s attached, max load on SSD-s and CPU: ~14W</li>
</ul>
<p>The Zimaboard, ISP modem/router box, my TP-Link router/Wi-Fi AP and my CyberPower
UPS all together use at most around 34W, all combined. That&rsquo;s even less than
what my Dell monitor uses at reasonably low brightness levels!</p>
<p>These tests are not scientifically accurate, but they should give you an idea on what
power consumption numbers to expect when running this setup.</p>
<h2 id="performance">
  <a class="heading-anchor" href="#performance">Performance<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I use a simple Prometheus Node Exporter + Grafana setup to view how much resources
my various servers use. My home server has lately either been an <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">ASRock Deskmini X300 based setup</a> or
an <a href="/posts/2022/05/10/thinkpad-as-a-home-server/">old ThinkPad T430</a>, and something that both had in common was that the CPU usage was
generally very low, mostly at or below the 10% mark. There would be bursty loads
from time to time and backup processes running that bump that up, but not significantly.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/prom-old.png">
    <img src="/posts/2023/10/09/zimaboard/media/prom-old_hu_708f14b1eed98d02.webp"
     width="1280"
     height="674"
     loading="lazy"
     decoding="async"
     alt="Typical CPU performance on a ThinkPad T430 acting as a home server.">

  </a>
  <figcaption class="center">Typical CPU performance on a ThinkPad T430 acting as a home server.</figcaption>
</figure>

<p>Memory usage of my setup was also quite low, with all my services and containers
fitting into 2GB during typical usage. With this information and some CPU performance
comparisons done, I knew that the Zimaboard will likely be able to handle my home
server tasks.</p>
<p>This board is not very powerful, but if you mainly rely on containerized workloads
and can rely on Intel QuickSync to accelerate media transcodes, then you&rsquo;ll be
just fine.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/prom-new.png">
    <img src="/posts/2023/10/09/zimaboard/media/prom-new_hu_85b12aa5a7e8f9b7.webp"
     width="1280"
     height="674"
     loading="lazy"
     decoding="async"
     alt="Zimaboard CPU usage, which includes migrating filesystems, creating new multi-TB
backups from scratch and a lot of Jellyfin playback and GPU-accelerated transcoding.
Pretty much the worst case scenario for this board.">

  </a>
  <figcaption class="center">Zimaboard CPU usage, which includes migrating filesystems, creating new multi-TB
backups from scratch and a lot of Jellyfin playback and GPU-accelerated transcoding.
Pretty much the worst case scenario for this board.</figcaption>
</figure>

<p>I was actually impressed with how well the GPU-accelerated transcode
worked on this machine once you set everything up properly.
If you&rsquo;re running Linux and Jellyfin,
run <code>vainfo</code> to get a list of supported codecs and make sure that you have hardware
decoding selected for those in Jellyfin settings. Also enable hardware encoding.
I checked with <code>intel_gpu_top</code> to see if work was offloaded to the GPU and saw
activity there, which means that hardware acceleration for Jellyfin worked out great!
<a href="https://jellyfin.org/docs/general/administration/hardware-acceleration/">Check the Jellyfin hardware acceleration for more details on other requirements
that have to be met for all of this to work.</a></p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/jellyfin-qs-conf.png">
    <img src="/posts/2023/10/09/zimaboard/media/jellyfin-qs-conf_hu_6c1ba97b1f638294.webp"
     width="715"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The Jellyfin QuickSync hardware acceleration config that works on my Zimaboard.
May not be 100% correct but so far have not encountered issues.">

  </a>
  <figcaption class="center">The Jellyfin QuickSync hardware acceleration config that works on my Zimaboard.
May not be 100% correct but so far have not encountered issues.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/intel-gpu-top.png">
    <img src="/posts/2023/10/09/zimaboard/media/intel-gpu-top_hu_c612456e5219acc0.webp"
     width="1280"
     height="204"
     loading="lazy"
     decoding="async"
     alt="intel_gpu_top during Jellyfin transcoded media playback. ">

  </a>
  <figcaption class="center">intel_gpu_top during Jellyfin transcoded media playback. </figcaption>
</figure>

<h2 id="caveats">
  <a class="heading-anchor" href="#caveats">Caveats<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The Zimaboard does ship with a Linux-based OS called CasaOS. However, I had no
intention of using it as I know what my requirements are and my infrastructure
is already decently documented and set up via Ansible, which is why I can&rsquo;t say
how good that experience is. I also did not test Windows 10 or 11.</p>
<p>During testing, I noticed that the USB 3 ports can act a bit weird. The Fedora
Server USB stick would not boot properly if connected to one of the USB ports,
and when doing other tests with external USB storage I noticed hiccups from time to time.
Not sure what might be the cause, but I&rsquo;m writing it down nevertheless. It&rsquo;s not
a dealbreaker for me luckily since I don&rsquo;t rely much on the USB ports in typical use anyway.</p>
<p>I did not test the PCI Express port, simply because I don&rsquo;t need it, yet. It&rsquo;s
a great addition, though, and opens up plenty of modding capabilities in the
future.</p>
<h2 id="fedora-server-and-btrfs">
  <a class="heading-anchor" href="#fedora-server-and-btrfs">Fedora Server and btrfs<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The Zimaboard gave me an opportunity to start fresh with my home server.</p>
<p>I made a leap: I&rsquo;ve ditched ZFS and am now running
Fedora Server with my storage being on a btrfs RAID1 setup, snapshotted
and backed up using <a href="/posts/2022/07/09/btrbk-is-awesome/">btrbk</a>.
It was a bit tricky to migrate and set everything
up regarding backups and snapshotting, but I got it working.</p>
<p>ZFS is great, but it has always felt like an unwanted guest in the Linux ecosystem.
The kernel developers don&rsquo;t care much for maintaining compatibility with ZFS since
it&rsquo;s not in the kernel due to licensing issues, and Ubuntu has been one of the few
distros that actually ships a kernel that includes ZFS built in. I didn&rsquo;t want
to be tied to Ubuntu forever, especially because of how they try to make <code>snap</code>
a thing. ZFS DKMS builds are generally okay on distros like Debian, but on
others you might find yourself not being able to access your data after a reboot
because of a kernel update.</p>
<p>btrfs has had some issues in the past, especially with the RAID5/6 setup, but
in my single and dual disk setups it has been solid for years, except for that one time around
2018-2019 when I ran btrfs RAID1 over USB storage. To be fair to btrfs, that
was a pretty stupid setup.</p>
<p>Before committing
to btrfs, I used two USB sticks to create a RAID1 setup and created real torture test scenarios.
Tests looked something like this:</p>
<ul>
<li>write a file to the filesystem</li>
<li>use <code>md5sum</code> to calculate a hash of it for verification purposes</li>
<li>completely wipe one USB drive with <code>dd</code></li>
<li>run <code>md5sum</code> to calculate the hash again (it matched every time)</li>
<li>run <code>btrfs scrub</code> on the filesystem to fix all errors</li>
<li>rinse and repeat with variations to this setup</li>
</ul>
<p>After doing all that, I was quite confident that this was going to work.</p>
<p>One thing to note with <code>btrfs</code>: if you&rsquo;re running any type of multi-disk and
redundant setup like RAID1 or RAID10, then make sure to include the mount option
<code>degraded</code> in <code>/etc/fstab</code> so that you can still mount your filesystem if one or
more of your drives fail. If you lose too many drives then it&rsquo;s still probably going to fail to boot.</p>
<p>Here&rsquo;s my <code>/etc/fstab</code> setup to serve as an example:</p>
<pre tabindex="0"><code>LABEL=turbo /turbo      btrfs subvol=turbo,compress-force=zstd:1,ssd,degraded,nofail            0 0
</code></pre><p>When doing the migration I kept all the paths the same, and each ZFS dataset
was recreated using <code>btrfs</code> subvolumes, which is why this filesystem is mounted on a top-level folder.</p>
<h2 id="alternatives">
  <a class="heading-anchor" href="#alternatives">Alternatives<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My notes for the next dream home server setup included a few candidates:</p>
<ul>
<li>
<p>the Zimaboard</p>
</li>
<li>
<p><a href="https://www.asustor.com/en/product?p_id=79">Asustor Flashstor 6</a> or <a href="https://www.asustor.com/en/product?p_id=80">Flashstor 12</a></p>
</li>
<li>
<p>a TinyMiniMicro style machine with at least two NVMe SSD slots</p>
</li>
</ul>
<p>The first two fall nicely into my requirements for the dream home server. I picked
the Zimaboard mainly because it&rsquo;s much cheaper and I was already running two SATA SSD-s
for my home server storage, so migrating would be really easy and I would not
have to buy any new drives.</p>
<p>If large capacity SATA SSD-s start becoming less common and NVMe SSD-s become
even cheaper than they already are, then I&rsquo;ll have to look into something like a Flashstor.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Overall, I&rsquo;m very happy with this purchase. The performance is just enough for
my services to work reasonably fast, the board uses very little power and it&rsquo;s
silent, and it looks good on my wall.</p>









<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/wallsetup.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/wallsetup_hu_263feac6bc54aaa1.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Oh it&#39;s a setup it&#39;s a setup it&#39;s a setup 🎶">

  </a>
  <figcaption class="center">Oh it&#39;s a setup it&#39;s a setup it&#39;s a setup 🎶</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/10/09/zimaboard/media/cablegore.jpg">
    <img src="/posts/2023/10/09/zimaboard/media/cablegore_hu_75af033ad64d88f6.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Managing the coax cable like this feels so wrong, and yet it works fine.">

  </a>
  <figcaption class="center">Managing the coax cable like this feels so wrong, and yet it works fine.</figcaption>
</figure>

<p>My setup is also quite flexible, so in case I need more resources, I can get
more Zimaboards and make them serve different purposes. However, it&rsquo;s more likely
that I&rsquo;m going to discover a new toy to experiment and play with by the time
I run out of resources on this one.</p>
<h2 id="2024-08-20-update">
  <a class="heading-anchor" href="#2024-08-20-update">2024-08-20 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I ran the Zimaboard for over half a year, but decided to switch back to
the <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">ASRock Deskmini X300.</a></p>
<p>I still love the low power consumption and the expandability, but I ended up putting more load on the system than I
initially anticipated CPU-wise (running over 20 different Docker containers, some heavy). Should&rsquo;ve guessed that it would happen eventually.</p>
<p>If it came with an embedded AMD Ryzen APU, then that would probably change things up quite a bit.</p>
<p>Zimaboard: still the closest thing to my dream home server, but it&rsquo;s that last little bit of performance being missing
that gets me. If your needs are moderate or low, then it&rsquo;s still a fantastic option, if the price is right.</p>
<p>My eyes are now on
the <a href="https://nascompares.com/2024/06/10/the-asustor-flashstor-gen2-performance-and-pci-lanes/">Asustor Flashstor Gen 2</a>
machines.
Up to 12 NVMe SSD-s plus 4 cores of AMD Ryzen goodness sounds too good to be true. Let&rsquo;s see what the reviews will say
once it&rsquo;s out.</p>
]]></content:encoded></item><item><title>Steam local network game transfers are a game-changer</title><link>https://ounapuu.ee/posts/2023/09/11/steam-cache/</link><pubDate>Mon, 11 Sep 2023 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/09/11/steam-cache/</guid><description>Setting up a Steam LAN cache has never been this easy, so I went ahead and did some testing with different configurations.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/09/11/steam-cache/media/cover_hu_8677bb4c48010087.jpg" width="1200" height="630" alt="Steam local network game transfers are a game-changer" /><p>Steam recently launched a new feature: <a href="https://help.steampowered.com/en/faqs/view/46BD-6BA8-B012-CE43">local network game transfers.</a></p>
<p>The idea is simple: if you have a game downloaded on another PC and you&rsquo;re both on the same local network, then Steam can download game data
from that PC, avoiding the need to download the game over public internet. Using this method you can reduce your internet
usage and enjoy faster download times.</p>
<p>I think this feature is absolutely brilliant. There are many homes out there, even in developed countries, where the
internet connection sucks. The speed might be capped at something very slow, such as 10 Mbit/s down, or you might
have a bandwidth cap in place. Perhaps you have multiple gaming PC-s and you want to avoid downloading 100+ gigabytes
worth of files over the internet to avoid hitting your bandwidth cap. In those situations being able to download your games to a PC that has a bunch of storage in it
makes a lot of sense.</p>
<p>This isn&rsquo;t the only way to achieve the same goal as <a href="https://lancache.net/">projects like LanCache exist.</a> However, with
Steam the setup is so simple that anyone who knows how to install Steam could achieve a similar result. The only caveat is that
you&rsquo;re limited to games installed through Steam, LanCache supports many other services.</p>
<p>Here are some ideas on how you can set up your own Steam cache.</p>
<h2 id="using-an-old-laptop">
  <a class="heading-anchor" href="#using-an-old-laptop">Using an old laptop<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you have an older laptop around and it has a gigabit Ethernet connection, then that can be a good candidate for
setting up a Steam cache.</p>
<p>The hardware I picked for this test is a ThinkPad T430. It has a 4 core CPU in it, 16 GB of RAM and plenty of ways
to attach storage to it. With storage I tried two approaches: using an older 1TB 2.5&quot; SATA HDD, and using
two Samsung 870 EVO 1TB SATA SSD-s in RAID0.</p>









<figure class="center">
  <a href="/posts/2023/09/11/steam-cache/media/image0.jpg">
    <img src="/posts/2023/09/11/steam-cache/media/image0_hu_ceb50a4db84a6f9c.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="It&#39;s a Steam cache. See, it says so right on the lid!">

  </a>
  <figcaption class="center">It&#39;s a Steam cache. See, it says so right on the lid!</figcaption>
</figure>

<p>The hard drive based solution isn&rsquo;t something I recommend, unless you plan on running two or more in a RAID-like setup.
The Steam cache use case seems to have hit the limits of the hard drive and that limited the transfer speeds
significantly.</p>
<p>The SSD-based setup was great! You might want to run something other than a RAID0 setup if you want to avoid a drive
failure taking your whole Steam library with you, I ran with this setup mainly to see where the limits are. The Steam
library is also something you can easily redownload, should things go really wrong.</p>
<p>One benefit of setting up an older laptop as a Steam cache is that you can take it with you to a place that has great
internet connectivity, download your games there and bring it back home with you. That&rsquo;s exactly what I did when
performing testing, I went to my local hackerspace, started the downloads, and came back half a day later to find
that over a terabyte worth of games had been downloaded. Doing the same on a slower home network would have taken days.
I guess the idea of <a href="https://en.wikipedia.org/wiki/IP_over_Avian_Carriers">IP over avian carriers</a>,
<a href="https://www.jeffgeerling.com/blog/2023/pigeon-still-faster-internet">or over humans</a>,
isn&rsquo;t dead yet.</p>
<p>When downloading the games, I noticed that Steam was hitting the CPU hard. Even on a decent 4-core Intel i7-3820QM the
CPU was often running at 100%. This meant that download speeds were usually around 500-700 Mbit/s, which is still good,
but nowhere near saturating the gigabit link that the laptop had.</p>









<figure class="center">
  <a href="/posts/2023/09/11/steam-cache/media/image1.jpg">
    <img src="/posts/2023/09/11/steam-cache/media/image1_hu_67e371a1c61477b.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The CPU is really struggling here.">

  </a>
  <figcaption class="center">The CPU is really struggling here.</figcaption>
</figure>

<p>Now that I had all the games downloaded, it was time to test the performance. The maximum transfer speeds were around
400-500 Mbit/s over my local network. I used my Steam Deck over an USB-C dock to start the downloads and picked the
internal NVMe SSD as the download target to avoid any storage speed bottlenecks. I would have liked to see speeds
close to 1 Gbit/s, but these speeds are still a massive improvement if your network speeds are something like
50 Mbit/s down, that&rsquo;s a 10x improvement!</p>









<figure class="center">
  <a href="/posts/2023/09/11/steam-cache/media/image2.jpg">
    <img src="/posts/2023/09/11/steam-cache/media/image2_hu_a89d48392fef01f8.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Typical transfer speeds observed with this setup.">

  </a>
  <figcaption class="center">Typical transfer speeds observed with this setup.</figcaption>
</figure>

<p>If you&rsquo;re worried about the fact that <a href="https://learn.microsoft.com/en-us/lifecycle/products/windows-10-home-and-pro">Windows 10 is going to lose support in October 2025</a>
and your Steam cache PC is not supported by Windows 11, then don&rsquo;t worry, you can do the same thing over Linux.</p>
<h2 id="using-a-virtual-machine">
  <a class="heading-anchor" href="#using-a-virtual-machine">Using a virtual machine<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you already have a NAS or a home server running, then you can create a new VM, add a bunch of storage to it,
setup the OS and Steam and you&rsquo;re good to go!</p>
<p>I did most of the testing on a Windows 10 VM and a 1TB HDD attached over USB 3.0. I setup the VM using a bog-standard
QEMU/KVM setup and set everything up through <code>virt-manager</code> in Linux. The only noteworthy part is that I set up the
network interface as a <code>macvtap</code> device, resulting in the VM showing up on my local home network as if it was a separate
PC. That step was taken to avoid any issues with the Steam instances on different PC-s not being able to transfer data
directly between each other.</p>
<p>My server runs on the <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">ASRock Deskmini X300</a>. It has plenty of CPU
performance, but during testing I ran into performance issues with the hard drive again. When I added SSD-based storage
to the VM, I found that the performance was great and quite similar to what I saw on the laptop.</p>
<p>The downside with the Windows 10 VM setup was the CPU usage. While the VM was idling, my server saw a noticeable
increase in idle CPU usage, utilizing about 10-20% of my CPU at all times. During transfers the VM was using most of
my CPU cores.</p>
<p>I did testing on a Linux VM to see if those are more efficient compared to a Windows 10 VM. The answer is obviously
&ldquo;yes&rdquo;, but there is one issue: I could not get Steam to work. At the time of testing, Steam had recently released a
bigger visual overhaul and I suspect that it might have something to do with those issues. The VM has no GPU
acceleration and opening Steam would result in &ldquo;Loading user data&rdquo; popup showing up, but nothing else happening.
I tried Ubuntu Desktop 22.04, Fedora Linux 38, and even Flatpak installations of Steam. All of them ran into the same
exact issue. There are probably ways to set Steam to not require GPU acceleration without opening its settings view
graphically, but I did not bother with that.</p>
<p>If you like to think in virtual machines, then this is a good option. However, it&rsquo;s not something I stuck with due to
the inefficient resource usage that a Windows 10 VM exhibited.</p>
<h2 id="using-containers">
  <a class="heading-anchor" href="#using-containers">Using containers<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This is the solution that I am currently running.</p>
<p>I recently found the <a href="https://docs.linuxserver.io/images/docker-webtop">LinuxServer.io webtop Docker images.</a> These
containers allow you to run various Linux desktop environments and distros on the same machine. You can connect to them
using the integrated KasmVNC solution over a browser. You can even use your GPU on the container host machine to improve
the video rendering performance in the container!</p>









<figure class="center">
  <a href="/posts/2023/09/11/steam-cache/media/image3.png">
    <img src="/posts/2023/09/11/steam-cache/media/image3_hu_5e25b945f3eec876.webp"
     width="1280"
     height="697"
     loading="lazy"
     decoding="async"
     alt="Fedora XFCE desktop running in a container.">

  </a>
  <figcaption class="center">Fedora XFCE desktop running in a container.</figcaption>
</figure>

<p>I picked the <code>fedora-xfce</code> option because Fedora is great, and the XFCE desktop environment is not that resource
intensive. I also utilized <a href="https://github.com/linuxserver/docker-mods/tree/universal-package-install">the linuxserver.io package install mod</a>
to install Steam on container startup. For networking, I created a separate Docker network using the <code>macvlan</code> driver to
achieve something similar to the VM setup, resulting in the container showing up as a separate machine on the local
network. Inside the container I set up Steam to start on startup using standard GUI tools that XFCE provides for this
purpose.</p>
<p>I really like this setup. I can easily point the Steam downloads to a larger storage pool and make use of all the CPU
power that Steam needs to perform the transfers.</p>
<p>During testing the limitation seems to have been my Steam Deck. I could still not saturate the 1 Gbit/s link.</p>
<p>The KasmVNC solution is quite nice and performant. The fact that I could use it in the browser makes it very convenient
to use as well.</p>
<p>The CPU usage during idle is very small, except for when you accidentally leave the Steam window open with animated
content being displayed. During file transfers the CPU gets a beating, but it&rsquo;s nothing the AMD Ryzen 7 5700G can&rsquo;t handle.</p>
<p>For storage I eventually ended up using a 1TB Lexar NVMe SSD. That&rsquo;s not enough to download all the games I have in my
Steam library, but at least I can download those games that take 20+GB of space and not have to worry about downloading
those over a slower internet connection.</p>
<p>I have not ended up using this setup too much yet, but I imagine that with games growing in size this is going to become
much more relevant for my Steam Deck. And if I were to move to the countryside where the only internet connection
available is a mobile 4G connection capped at 10 Mbit/s down, then this setup would be fantastic to have.</p>
<h2 id="tech-tips">
  <a class="heading-anchor" href="#tech-tips">Tech tips<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you intend to run a similar setup, I recommend enabling &ldquo;Scheduled updates&rdquo; to run during the night. I set mine up
to auto-update games between 00:00 and 06:00, which is where I&rsquo;m likely going to sleep and not notice that game downloads
are taking place. Steam is notorious for hogging all of the bandwidth on the network and this nifty feature helps
avoid disturbing other users on the network.</p>
<p>If you&rsquo;re performing the initial mass download of your games but would like for it to take place during scheduled times, start downloading
all of the games and then restart your machine. When Steam starts up again, you&rsquo;ll notice that all your games are
queued up nicely to download during your scheduled updates time slot.</p>
<h2 id="caveats">
  <a class="heading-anchor" href="#caveats">Caveats<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This setup is not ideal and <a href="https://help.steampowered.com/en/faqs/view/46BD-6BA8-B012-CE43">the Steam support page highlights it well.</a>
For example, this setup does not work in fully offline situations as internet connectivity is required for the initial
setup of the local network game transfer. I recommend giving that page a read to understand the requirements and technical specifics of this setup.</p>
]]></content:encoded></item><item><title>The IKEA-powered homelab on a wall</title><link>https://ounapuu.ee/posts/2023/09/07/ikea-powered-homelab/</link><pubDate>Thu, 07 Sep 2023 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/09/07/ikea-powered-homelab/</guid><description>This pegboard can fit so much compute power on it!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="The IKEA-powered homelab on a wall" /><p>I recently learned about <a href="https://www.ikea.com/us/en/cat/skadis-series-37813/">the IKEA SKÅDIS series</a>, which is a
pegboard that supports a variety of extras. During my self-hosting journey having to figure out the best
place for putting all my compute stuff to has always been at the back of my mind, especially due to limited floor
space at my home. This pegboard gave me an idea.</p>









<figure class="center">
  <a href="/posts/2023/09/07/ikea-powered-homelab/media/image1.jpg">
    <img src="/posts/2023/09/07/ikea-powered-homelab/media/image1_hu_fd2515f9af042625.webp"
     width="825"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Behold: the homelab on a wall!">

  </a>
  <figcaption class="center">Behold: the homelab on a wall!</figcaption>
</figure>

<p>Note that this idea also applies to other types of pegboards that you can find, I just went with the IKEA one for
<em>aesthetics</em> (and the wife approval factor).</p>
<p>The layout was improvised during the assembly process, but in the end I&rsquo;m quite happy with how this turned out.
Everything is held in place with zip ties of varying sizes. The biggest ones I used are 360x4.5mm, which fit nicely
due to the slot width of the pegboard being 5mm. Some of the zip tie ends have been cut off for aesthetic reasons, but
most of them are intact in case I want to perform maintenance on this setup.</p>
<p>There are some improvements that I might implement to a revision of this board. The USB cables connecting the external
SSD-s seem to be just small enough to be routable behind the pegboard. Other cables that are visible can probably
be hidden on the other side as well, giving the setup a much cleaner look.</p>
<p>I also installed a second pegboard to have access to most commonly used cables and other stuff that I usually store
on my table in a chaotic fashion. It&rsquo;s a work in progress, but it looks very promising already.</p>









<figure class="center">
  <a href="/posts/2023/09/07/ikea-powered-homelab/media/image2.jpg">
    <img src="/posts/2023/09/07/ikea-powered-homelab/media/image2_hu_3040c8d60e58d5b5.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The misalignment is a representation of my struggle to install the damn thing properly. I&#39;ll fix it eventually.">

  </a>
  <figcaption class="center">The misalignment is a representation of my struggle to install the damn thing properly. I&#39;ll fix it eventually.</figcaption>
</figure>

<p>Maintenance is not going to be very easy on this setup. Luckily the UPS should be maintenance-free for the next 2-4
years or whenever the battery dies, and with the ASRock Deskmini X300 I can unscrew the 4 screws on the back and slide
the thing out without having to take off the whole pegboard. I hope that the external SSD-s don&rsquo;t die on me soon, but
if they do, then sliding them out of the zip ties should not be that difficult.</p>
<p>Those more familiar with my content might see echoes of <a href="/posts/2021/03/20/whacky-setups-1/">the seedbox on a wall</a>
in this post.</p>
]]></content:encoded></item><item><title>Why you might not want to publicly self-host a Wikipedia clone</title><link>https://ounapuu.ee/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/</link><pubDate>Tue, 29 Aug 2023 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/</guid><description>Does not apply if you like spam. No, not that one.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Why you might not want to publicly self-host a Wikipedia clone" /><p>A while ago I wrote about how easy it is to <a href="/posts/2021/12/09/self-hosting-wikipedia/">download an archive of Wikipedia and host it anywhere
you want using Kiwix.</a></p>









<figure class="center">
  <a href="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/image.jpg" aria-label="View full-size image">
    <img src="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/image_hu_5f96e92e793837d0.webp"
     width="920"
     height="518"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Here are a few things you might want to consider before doing so yourself.</p>
<h2 id="the-spam">
  <a class="heading-anchor" href="#the-spam">The spam<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have a specific e-mail address set up so that readers of my blog can reach out to me no matter where they see my post.
I knew about the risk of spam, but receiving genuine feedback and questions is something I appreciate a lot and I&rsquo;m
willing to mark everything else as spam if needed.</p>
<p>What I did not expect was the amount of spam that originates from my self-hosted copy of Wikipedia, or that they&rsquo;d
use the e-mail that is present on the main <code>ounapuu.ee</code> domain.</p>
<p>The scheme seems to work like this:</p>
<ul>
<li>crawl the web</li>
<li>find links to genuine sources that have broken (HTTP 404 errors)</li>
<li>spam the owner of the site with a politely worded e-mail template that asks you to fix those broken links with
these new ones that link to some marketing garbage or SEO spam</li>
<li>go to step 0</li>
</ul>
<p>And the worst part is that this probably works for a lot of smaller sites with non-technical owners.</p>
<p>I&rsquo;ve deleted most of the spam but have some recent examples (click on the image to see the higher quality image).</p>









<figure class="center">
  <a href="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/legitstuff1.png" aria-label="View full-size image">
    <img src="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/legitstuff1_hu_505404d592d58e04.webp"
     width="1027"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>










<figure class="center">
  <a href="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/legitstuff2.png" aria-label="View full-size image">
    <img src="/posts/2023/08/29/why-you-might-not-want-to-self-host-wikipedia/media/legitstuff2_hu_cb16e2ecc0738514.webp"
     width="1280"
     height="753"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Wikipedia has a lot of broken links and since my copy of it will always be a little bit out of date, I will probably
keep receiving spam like this until the end of time.</p>
<h2 id="security">
  <a class="heading-anchor" href="#security">Security<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Turns out that the version of Kiwix that you can <code>sudo apt install</code> in Ubuntu Server 22.04 LTS is really out of date.
I learned about that when <a href="https://www.ria.ee/en/cyber-security/handling-cyber-incidents-cert-ee/monitoring-cyberspace-and-impeding-incidents">CERT-EE</a>
reached out to me about an <a href="https://github.com/kiwix/kiwix-tools/issues/605">XSS vulnerability that Kiwix had</a>.</p>
<p>If you&rsquo;re running a Kiwix version older than 12.0.0, then congratulations, you have this vulnerability!</p>
<p>If your distro ships the latest version (Arch Linux, Fedora Linux etc.), then you&rsquo;re good to go!</p>
<p>If your distro doesn&rsquo;t, then feel free to use the <a href="https://github.com/orgs/kiwix/packages">Kiwix Docker images</a>
to get around that limitation.</p>
<p>A very basic example command that should get you started:</p>
<pre tabindex="0"><code>docker run --rm  \
    --name=kiwix \
    -v /path/to/content/:/data \
    ghcr.io/kiwix/kiwix-serve:latest \
    /data/*.zim
</code></pre><h2 id="2024-09-05-update-llm-bots">
  <a class="heading-anchor" href="#2024-09-05-update-llm-bots">2024-09-05 update: LLM bots!<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Well, it turns out that Kiwix is horribly inefficient at disk usage when LLM data scrapers are hitting it at 50+ requests
per second.</p>
<p>The following is the result of running Kiwix for 4 days. Over 8 TB of disk reads is incredibly wasteful.</p>
<pre tabindex="0"><code>CONTAINER ID   NAME                          CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
734d8e1b4385   kiwix                         50.28%    10.36GiB / 27.27GiB   38.00%    7.73GB / 94.7GB   8.45TB / 12.9GB   7
</code></pre><p>I&rsquo;ve decided to finally take down my instance of <code>kiwix.ounapuu.ee</code> as a result.</p>
]]></content:encoded></item><item><title>How I blew up my backup server (Valve pls fix)</title><link>https://ounapuu.ee/posts/2023/06/10/how-i-blew-up-my-backup-server/</link><pubDate>Sat, 10 Jun 2023 12:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/06/10/how-i-blew-up-my-backup-server/</guid><description>All of this could have been avoided if I didn't insist on making backups of my Steam Deck.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/06/10/how-i-blew-up-my-backup-server/media/cover_hu_597e9432fe026b5c.jpg" width="1200" height="630" alt="How I blew up my backup server (Valve pls fix)" /><p>It all started with me getting a Steam Deck.</p>
<h2 id="background">
  <a class="heading-anchor" href="#background">Background<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>After getting familiar with the Steam Deck and how the Proton compatibility layer works, I decided to write a
backup script that would back up everything in the home folder, excluding the Steam games themselves due to the sheer <em><strong>girth</strong></em>
of modern games (how the hell has GTA V ballooned up to 100+GB???).</p>
<p>Among the folders that I backed up was <code>compatdata</code>, a folder that contains files that Proton needs
to make Windows games run. If you browse the folder, the contents look like a mini-Windows installation,
and among those files you can also find your savegames. It made sense to me to back up this folder, and
I was quite happy to know that no matter what happens, my game saves would be safe as long as I made a copy
of this folder.</p>
<p>Fast forward a few weeks: I&rsquo;m doing some changes to my self-hosting infrastructure and decide to
redeploy changes to a backup server that I have. Nothing fancy, just Ansible roles that make sure
that the backup server has some configuration present and that the backup folder has the right permissions.</p>
<p>The step looks something like this:</p>
<pre tabindex="0"><code>- name: Fix permissions
  ansible.builtin.file:
    name: /path/to/backups
    state: directory
    owner: user
    group: user
    recurse: yes
</code></pre><p>Everything was okay until I saw this.</p>









<figure class="center">
  <a href="/posts/2023/06/10/how-i-blew-up-my-backup-server/media/image-0.png">
    <img src="/posts/2023/06/10/how-i-blew-up-my-backup-server/media/image-0_hu_a3aee0eb19da0519.webp"
     width="1280"
     height="121"
     loading="lazy"
     decoding="async"
     alt="Uh-oh.">

  </a>
  <figcaption class="center">Uh-oh.</figcaption>
</figure>

<p>After trying to recover the backup server and giving up as soon as I found that I cannot log in as root or
use <code>sudo</code>, I gave up on doing that over the network and decided to get physical acccess to the server.
One reinstall and Ansible run later, the server is okay again.</p>
<h2 id="investigation">
  <a class="heading-anchor" href="#investigation">Investigation<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>How did we end up here though?</p>
<p>The backups from the Steam Deck are made to my home server using <code>rsync</code>. The Steam Deck is just a Linux
machine, after all, and it made the most sense to me as I could make a backup that preserves all the
permissions and links. Should I ever screw something up, I can run the same script in reverse and have everything working
as it used to. I would hate setting up all my games and customizations again.</p>
<p>The script looked something like this.</p>
<pre tabindex="0"><code>rsync -aAXzv --delete-before /home/deck/ backupuser@myserver:/path/to/steamdeck/ \
  --exclude .local/share/Steam/steamapps/common \
  --exclude .local/share/Steam/steamapps/downloading

sudo shutdown now
</code></pre><p><em>Free tech tip: you can create a desktop entry for any script, add it to Steam, and run it
within the Steam Deck UI when you&rsquo;re done playing. You&rsquo;ll have a backup and the
system will shut down automatically once it&rsquo;s done!</em></p>
<p>Nothing suspicious about the script, right?</p>
<p>There&rsquo;s one problem with it: <code>rsync</code> also sends over links. These come in various types (symlinks, hard links)
and act as a pointer to another file or folder. Turns out that Proton (or Wine) loves using symlinks. Most
usages I saw were pointing towards common distributions of Proton, which makes perfect sense since it saves
disk space.</p>
<p>There are also links that point to the root folder <code>/</code>. The use case for these seems also makes sense:
present the game with a drive like <code>Z:</code>, and point it to <code>/</code> on Linux side, and now the user can easily
navigate their whole file system within the context of the game they&rsquo;re running. Maybe you want to install
the game or its add-ons into a different folder, or maybe you want to load a save game that you
have somewhere on your Steam Deck.</p>









<figure class="center">
  <a href="/posts/2023/06/10/how-i-blew-up-my-backup-server/media/image-1.png" aria-label="View full-size image">
    <img src="/posts/2023/06/10/how-i-blew-up-my-backup-server/media/image-1_hu_7036cf8e5f4678a8.webp"
     width="1280"
     height="62"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Just one problem with this: what happens when you have this symlink on another machine, such as my backup server,
and you use Ansible to set the permissions for a folder containing this symlink, recursively?
And what if the <code>follow</code> setting in Ansible <a href="https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#parameter-follow">is on by default since Ansible 2.5</a>?</p>
<p>Turns out that the answer is that you&rsquo;re going to mess up the file permissions on the whole machine, and
most things stop working at that point. I could still login to one user on that box, but I could not do
anything that would help recover the state of the machine at that point.</p>
<h2 id="the-fix-">
  <a class="heading-anchor" href="#the-fix-">The fix (?)<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>There are many options for avoiding this problem, or at least working around it. I&rsquo;m not sure what the perfect
fix looks like. In case you know one, let me know.</p>
<p>One thing I added to my backup script was <code>--no-links</code>, which instructs <code>rsync</code> to not copy symlinks. That setting
has to appear after the first batch of arguments (<code>rsync -aAXzv</code>) because otherwise it will be overridden by the <code>-a</code>
parameter.</p>
<p>I also updated my Ansible setup to avoid setting the permissions for the Steam Deck backup folder as a precaution.</p>
<p>The major downside with my tweaks is that I don&rsquo;t really have a &ldquo;full&rdquo; backup of my Steam Deck anymore.
I do have backups of my game saves, but recovering from the backup will become a bit of a hassle due to
me having to find and copy the game saves manually to the new <code>compatdata</code> folders since the backed up
ones are missing all the symlinks to Proton/Wine-managed dependencies.</p>
<p>Alternatively I can consider using a backup tool like <code>restic</code> that <a href="https://restic.readthedocs.io/en/latest/040_backup.html#backing-up-special-items-and-metadata">should
preserve symlinks</a>. I&rsquo;ll just
need to also test recovering from that backup method.</p>
<p>Either way I can&rsquo;t really blame Valve, Wine or Proton developers for my own fuck-up.
They used symlinks in a way that allowed them to save disk space and give the user
easier access to their files in-game. It&rsquo;s just unfortunate that I learned about
this setup the hard way.</p>
<p>Completely unrelated to my issue, but I can&rsquo;t help but remember <a href="https://github.com/valvesoftware/steam-for-linux/issues/3671">that one person whose machine got wiped by
Steam.</a></p>
]]></content:encoded></item><item><title>I held a talk about my self-hosting adventure!</title><link>https://ounapuu.ee/posts/2023/05/26/my-selfhosting-adventure/</link><pubDate>Fri, 26 May 2023 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/05/26/my-selfhosting-adventure/</guid><description>I had the opportunity to talk about my self-hosting adventure and share some tech tips at k-space, the hackerspace in Tallinn, Estonia.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/05/26/my-selfhosting-adventure/media/cover_hu_c51564873470915e.jpg" width="1200" height="630" alt="I held a talk about my self-hosting adventure!" /><p>There are two reasons why I haven&rsquo;t written much lately, and one of them is that I was cooking up a
talk about self-hosting, more specifically my own self-hosting adventure (the other one is the Steam Deck, more about
that in the future).</p>
<p>The talk took place on May 25th 2023 at <a href="https://www.k-space.ee/">k-space, a hackerspace in Tallinn, Estonia</a>.</p>
<p>This talk was livestreamed and you can watch the recording by <a href="https://www.youtube.com/watch?v=V5dMKLHO4dM">clicking on this link</a>.</p>
]]></content:encoded></item><item><title>Tiered storage: use the right tool for the job</title><link>https://ounapuu.ee/posts/2023/03/26/tiered-storage/</link><pubDate>Sun, 26 Mar 2023 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/03/26/tiered-storage/</guid><description>A short ramble about something I realized over the years with my self-hosting setup.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/03/26/tiered-storage/media/cover_hu_55d647cb3831383b.jpg" width="1200" height="630" alt="Tiered storage: use the right tool for the job" /><p>Hard drives are still the default choice for many homelab and data hoarding
enthusiasts. They still hold the gigabytes per dollar advantage over SSD-s (for now),
and if you buy the big external drives and take the drives out of the enclosures,
you can get a pretty good deal.</p>
<p>Spinning rust has one obvious downside: it&rsquo;s slow, both in maximum transfer
speeds and in latency. For most use cases this is fine, but if you run a service
that depends on a database or if you have a lot of clients relying on that storage,
you&rsquo;ll find that hard drives just won&rsquo;t cut it.</p>
<p>At this point you probably don&rsquo;t want to <a href="https://www.jeffgeerling.com/blog/2022/building-fast-all-ssd-nas-on-budget">splurge and build an all-SSD NAS</a>,
so you look up caching solutions. Depending on your platform, you&rsquo;ll have all sorts
of options.</p>
<p>If you run ZFS, you&rsquo;ll likely learn about L2ARC and why you probably don&rsquo;t want
to use it (hint: check your ZFS ARC hit/miss ratio first).
Or <a href="https://klarasystems.com/articles/what-makes-a-good-time-to-use-openzfs-slog-and-when-should-you-avoid-it/">SLOG</a>,
or the <a href="https://forum.level1techs.com/t/zfs-metadata-special-device-z/159954/">special metadata device.</a>
And in most cases the top recommendation is to add as much RAM as you can to
the system so that you can benefit from a bigger filesystem cache. You&rsquo;ll see
some improvements, but not all workloads will benefit from this and you might
up being disappointed after all that work.</p>
<p>I cannot speak for options on other platforms, but in most cases the idea is
similar: buy a separate sacrificial SSD and use it as a cache drive.</p>
<h2 id="cache-is-not-king">
  <a class="heading-anchor" href="#cache-is-not-king">Cache is (not) king<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Take a moment and think about what type of data you&rsquo;re storing.</p>
<p>Here&rsquo;s an overview based on my own setup:</p>
<ul>
<li>archived YouTube videos (bunch of big files)</li>
<li>cat pictures (bunch of small and big files)</li>
<li>services that utilize a database (bunch of smaller files)</li>
<li>various installation media (bunch of big files)</li>
<li>backups of physical disks (bunch of big files)</li>
<li>a copy of my Steam library (bunch of big and small files)</li>
<li>a web server (bunch of small files)</li>
</ul>
<p>Most of the data I have is accessed relatively infrequently, and when it is,
the performance requirements are not that high. Any hard drive based array
will be able to handle streaming video or copying big bulky files over the
network.</p>
<p>Data that is more latency sensitive, such as Nextcloud, Jellyfin (and its
.sqlite DB) and PostgreSQL, take up a relatively small part of the overall
storage.</p>
<p>In this case (and assuming that the setup allows for it physically), the
solution is simple: add a smaller flash-based storage pool to the
setup and use it for data that benefits from it.</p>
<p>I experimented with a similar setup in the past with two 8 TB hard drives holding
all the big files and a pair of 250 GB SSD-s handling Nextcloud and other
services. Now I had the best of both worlds.</p>
<p>In short, you don&rsquo;t need to mess around with a fancy caching solution if your
storage usage patterns are simple and predictable. If you do a little bit of
investigation once, you can bypass all the logic that is usually built into
various caching solutions and get a better end result as no caching solution is
100% perfect.</p>
]]></content:encoded></item><item><title>LattePanda V1 - my experience with a Raspberry Pi alternative</title><link>https://ounapuu.ee/posts/2023/02/28/lattepanda-v1/</link><pubDate>Tue, 28 Feb 2023 09:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/02/28/lattepanda-v1/</guid><description>I got a LattePanda V1 and gave it a go as a Raspberry Pi replacement for my self-hosting setup. Here's how it went.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/02/28/lattepanda-v1/media/cover_hu_d0bf1305a5f9620b.jpg" width="1200" height="630" alt="LattePanda V1 - my experience with a Raspberry Pi alternative" /><p>As with many homelab experiments around 2022/2023, it all started with Raspberry Pi-s
being either out of stock or absurdly overpriced.</p>
<p>I once noticed a listing for a <a href="https://www.lattepanda.com/lattepanda-v1">LattePanda V1</a> on a local auction site.
The price was reasonable at 45 EUR, and after I looked at the specifications, I
had to get one to play around with.</p>
<p>The auction site usually sells used items, but this LattePanda V1 was brand new
in box, which surprised me. I got the 2GB RAM/32GB eMMC option.</p>
<p>I put the LattePanda through its paces, and here&rsquo;s what I learned.</p>
<p>Please note that my use cases are more on the software side, I did not try out
the hardware capabilities that SBC-s are also associated with (GPIO, camera/display
ports etc).</p>
<h2 id="the-hardware">
  <a class="heading-anchor" href="#the-hardware">The hardware<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>What makes the LattePanda V1 special is that it&rsquo;s based off of an x86 CPU.
Mine came with an <a href="https://ark.intel.com/content/www/us/en/ark/products/93361/intel-atom-x5z8350-processor-2m-cache-up-to-1-92-ghz.html">Intel Atom x5-Z8350</a>.
4 cores, not very fast ones, but similar or better to what you&rsquo;d find in a
Raspberry Pi 4. Most single-board computers usually come with an ARM-based CPU.</p>
<p>The board behaves like any normal PC. You power it on, you see the LattePanda
logo, and the OS just starts up. Smashing the &ldquo;Delete&rdquo; key during the boot
will direct you to the UEFI settings. Since this board is marketed towards
the technical crowd, it has so many settings that you can play with.
Definitely more than what I&rsquo;d know to do with.</p>
<p>The board comes with Windows 10 preinstalled. I booted it up and gave it a go,
and it was slow as molasses while it downloaded the latest updates. At one
point I reinstalled Windows 10 and ran into issues. It &ldquo;works&rdquo;, but I had trouble
getting any Intel GPU drivers installed on it, which rendered it almost useless
for any media playback use case that I could have used it for.</p>
<p>The port selection is okay. It comes with 100 Mbit/s Ethernet, one USB 3.0 port
and two USB 2.0 ports. I could get around 350 MB/s out of the USB 3 port with
an external SSD, and the USB 2 ports pulled anywhere between 15-40 MB/s,
depending on my luck. If you fancy a gigabit connection, then an USB-to-Ethernet
adapter might do the trick.</p>
<p>Adding one external HDD or SSD over USB is okay and works well, but after
adding a second one I noticed issues with either one of the disks not receiving
enough power. If you intend to use the LattePanda V1 as the brains for a cheap
NAS, then use drives that are powered externally.</p>
<p>The eMMC storage on the board is decent. Regarding performance it&rsquo;s somewhere
between a hard drive and a proper SSD, and the sequential read speeds max out
around 150 MB/s. My main concern with it is the durability. The eMMC chip is probably hidden
behind the metal shielding on the board and replacing it (if that is even
possible) might turn out to be tricky. <code>ls -lah /dev/disk/by-id/</code> lists the
eMMC chip as <code>mmc-DA4032</code>, which a little bit of Googling refers to it being a
SanDisk chip.</p>
<p>The microSD card port works, but either booting from the microSD card is not
possible or the board was a bit temperamental when I gave it a go with Ubuntu Server 22.04.</p>
<p>The board runs hot in its barebones configuration, any decent load over a longer time period
will result in the CPU throttling itself. I recommend rigging up a metal
heat sink to the bottom of the board to avoid throttling and stability issues
under very high load. A thermal pad, a piece of metal, and a bunch of zip ties
will do wonders.</p>









<figure class="center">
  <a href="/posts/2023/02/28/lattepanda-v1/media/image-1.jpg">
    <img src="/posts/2023/02/28/lattepanda-v1/media/image-1_hu_e1f7f36d88fce326.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Do not look at the bend.">

  </a>
  <figcaption class="center">Do not look at the bend.</figcaption>
</figure>

<h2 id="the-linux-experience">
  <a class="heading-anchor" href="#the-linux-experience">The Linux experience<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>When experimenting with Linux, I found a couple of annoyances. The LattePanda V1
seems to have a display connector on board. However, in Linux it turned out to
be an annoyance as the system always presented a 1024x768 display being
connected to the system. Booting into a Fedora Linux liveUSB environment will
lead you to staring a blank view with only the wallpaper present.
Playing with settings in UEFI did not lead to any improvements. What works is
<a href="https://unix.stackexchange.com/a/526619">adding a kernel parameter</a>:
<code>video=DSI-1:d</code>. With Fedora Linux, if you apply this fix in GRUB when first
booting into the liveUSB environment, it will persist after the installation
is done.</p>
<p>Once I had Fedora Linux booted up, I did not have a good time. The display
flickered when I dragged the mouse near the edges and the performance was awful.
It didn&rsquo;t take long for the desktop session to crash.</p>
<p>One of the main reasons I wanted to experiment with this setup was the low power
usage of this board. The LattePanda V1 idles at around 3 watts, and under a high
CPU load generated with <code>stress -c 4</code> I could get it to 5-6 watts. This made it
a great candidate for running this website and Wireguard VPN 24/7 at home.
I ended up installing Ubuntu Server 22.04 on it and actually ran this website
off of it for about a week or so.</p>
<p>The reason I stopped using the LattePanda V1 for that purpose was the
performance. The 100 Mbit/s Ethernet wasn&rsquo;t a disaster, but it did set limits
to how much traffic I could push through the board. What made me reconsider was
the CPU performance. Simply put: SSL encryption speeds were about 5-10x slower
than on my ThinkPad T430 that ran as a server before.</p>
<p>My performance testing wasn&rsquo;t scientific or anything, but I did run simple tests.
One of the involved running <code>curl</code> against resources, such as an image on my
blog, in an infinite loop and over multiple threads. The ThinkPad T430 peaked at
around 650 Mbit/s of network bandwidth while the LattePanda V1 struggled at
around 60 Mbit/s.</p>
<p>After looking for some other benchmarking options that I could set up really
quickly, I also gave <a href="https://serverfault.com/a/160807">ApacheBenchmark a go</a>.
This more-or-less confirmed my findings and the requests per second results
are the following:</p>
<ul>
<li>ThinkPad T430: 301.72</li>
<li>LattePanda V1: 55.86</li>
</ul>









<figure class="center">
  <a href="/posts/2023/02/28/lattepanda-v1/media/bench-T430.png">
    <img src="/posts/2023/02/28/lattepanda-v1/media/bench-T430_hu_558c4a4c431b3448.webp"
     width="626"
     height="733"
     loading="lazy"
     decoding="async"
     alt="ApacheBenchmark results for the ThinkPad T430.">

  </a>
  <figcaption class="center">ApacheBenchmark results for the ThinkPad T430.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2023/02/28/lattepanda-v1/media/bench-lattepanda.png">
    <img src="/posts/2023/02/28/lattepanda-v1/media/bench-lattepanda_hu_84fa5fa602aa54cc.webp"
     width="626"
     height="708"
     loading="lazy"
     decoding="async"
     alt="ApacheBenchmark results for the LattePanda V1.">

  </a>
  <figcaption class="center">ApacheBenchmark results for the LattePanda V1.</figcaption>
</figure>

<p>The LattePanda V1 was over 5 times slower in that test. With a slow internet
uplink this might not matter much, though.</p>
<p>I ended up putting the T430 back in service after doing more calculations.
One idea I had with the LattePanda V1 was to have that run 24/7 due to its
low idle power usage and have another beefy server run during certain hours.
I liked that idea until I calculated the difference in power savings. Having
the main server with around 12 W of idle power turn off for 6 hours and the
LattePanda running at the same time would have actually increased the total
power consumption of the setup compared to having the main server running 24/7.</p>
<p>The math will make sense if your main server uses much more power. Most desktop
PC-s that I have seen idle around 35-50 W and rack-mounted servers use even
more than that, so in those situations this might make more sense. <a href="https://maximiliangolla.com/blog/2022-10-wol-plex-server/">Or you can
whip up a solution that starts and stops machines in your homelab on-demand.</a></p>
<p>Oh, and don&rsquo;t expect to run CPU or GPU based transcoding off of this thing with
Jellyfin. It works okay for certain video formats and resolutions, but a 1080p
H.265 video transcoded to H.264 is just not fast enough on this machine.</p>
<h2 id="a-suitable-use-case">
  <a class="heading-anchor" href="#a-suitable-use-case">A suitable use case<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I might change my mind at one point and give the LattePanda a go again as a
low power web server. <a href="/posts/2022/11/01/finding-use-case-for-raspberry-pi/">I hate unused hardware</a>,
which is why this LattePanda V1 is now serving as an offsite backup. The USB 3
port makes sense for attaching a bigger storage device and if you run ZFS, you
can also send your whole filesystem to it with <code>zfs send/receive</code> or <code>syncoid</code>.
I haven&rsquo;t had much luck with ARM and ZFS, but with the LattePanda and its
x86-based CPU I have not had issues.</p>









<figure class="center">
  <a href="/posts/2023/02/28/lattepanda-v1/media/image-2.jpg">
    <img src="/posts/2023/02/28/lattepanda-v1/media/image-2_hu_6b11150490335f68.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="LattePanda V1 in its final form: a backup endpoint.">

  </a>
  <figcaption class="center">LattePanda V1 in its final form: a backup endpoint.</figcaption>
</figure>

<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>All-in-all, it&rsquo;s a neat little board that shows signs of instability from time to time.
If you intend to just run Ubuntu Server on it and your workloads are not
very performance critical, then it might work out well for you. Think of it
like a juiced-up Raspberry Pi 4 to get an idea of what it might be suitable for
regarding performance.</p>
<p>It did not fit the use case I intended to use it for, but I&rsquo;m still happy that
I could play around with this board. It was fun!</p>
]]></content:encoded></item><item><title>ThinkPad as a server: the follow-up</title><link>https://ounapuu.ee/posts/2023/01/27/thinkpad-as-server-followup/</link><pubDate>Fri, 27 Jan 2023 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2023/01/27/thinkpad-as-server-followup/</guid><description>The ThinkPad as a server is back, this time with a couple of adjustments.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2023/01/27/thinkpad-as-server-followup/media/cover_hu_cbe0fc525453c7fc.jpg" width="1200" height="630" alt="ThinkPad as a server: the follow-up" /><p>It&rsquo;s been a while since I last wrote about my <a href="/posts/2022/05/10/thinkpad-as-a-home-server/">ThinkPad T430 that was tasked with being a home server.</a>
After doing some experiments with my setup a couple of times, it is once again the main server for all my self-hosting
needs. However, this time I have made some adjustments.</p>
<h2 id="background">
  <a class="heading-anchor" href="#background">Background<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The monstrosity that you&rsquo;re looking at is what I&rsquo;d call &ldquo;the minimum viable ThinkPad as a server&rdquo;. To be fair, you <em>could</em>
go even more minimal by ripping out everything but the motherboard and the drives, but for my use case this is how far I
was willing to go.</p>
<p>In my previous post about this setup, I mentioned that the T430 suffered unexpected shutdowns under certain situations,
which usually involved running the fan at the lowest speed, moderate to high CPU load, and a lot of storage activity.
It wasn&rsquo;t the CPU as the temperatures were way below the critical point, so I suspected either the motherboard or the
storage running hot and tripping some sensor that I wasn&rsquo;t aware of.</p>
<p>For a while now, I have been thinking about running the T430 as bare as possible. One idea involved taking the bare
motherboard and the storage and slapping it on an acrylic sheet with some stand-offs, which should give it the best
chance at cooling. Unfortunately I didn&rsquo;t have enough time to commit to this, and that setup would have had some
downsides as well. At some point an idea popped to my mind: I could probably achieve a similar result by stripping
everything but the bare necessities from the laptop and improve the cooling as a result. That&rsquo;s how I ended up with
what you just saw.</p>
<h2 id="t430-stripped">
  <a class="heading-anchor" href="#t430-stripped">T430, stripped<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I ended up removing the following from the T430:</p>
<ul>
<li>palm rest</li>
<li>smart card reader</li>
<li>Bluetooth chip</li>
<li>WiFi chip</li>
<li>the whole display assembly</li>
</ul>
<p>This was in part motivated by the fact that those parts are the ones that are not in the best shape on my main ThinkPad
T430 that I use as an actual laptop. The other part was this nagging feeling that the most powerful PC that I own
<a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">(the ASRock DeskMini X300)</a> was woefully underutilized as my home
server.</p>
<p>The keyboard had to stay because the power button is part of the keyboard assembly. There are ways to power on the
laptop without the keyboard:</p>
<ul>
<li>put the laptop in a dock and use the power button that is present on the dock</li>
<li>short a specific pin on the keyboard connector to ground</li>
</ul>
<p>I do have some extra ThinkPad docks around that I could have used for this purpose, but it would have made the setup
bulkier, which is why I did not go for that, at least not yet.</p>
<p>There is also an option in UEFI settings that can be used to turn the laptop on by connecting the charger
(&ldquo;Power on with AC attach&rdquo;), but that only seems to work if you have a battery connected and after you have turned the
laptop on manually once. The same caveat applies for Wake on LAN functionality. If the laptop overheats or it runs out
of battery completely, then you need to manually power it on.</p>
<h2 id="the-cooling-situation">
  <a class="heading-anchor" href="#the-cooling-situation">The cooling situation<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Removing the palm rest reveals something that might be related to the unexpected shutdowns that I observed with this
setup previously.</p>









<figure class="center">
  <a href="/posts/2023/01/27/thinkpad-as-server-followup/media/image-0.jpg" aria-label="View full-size image">
    <img src="/posts/2023/01/27/thinkpad-as-server-followup/media/image-0_hu_1c812eb038d9345b.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Under this area is a chip on the motherboard that seems to generate a modest amount of heat. While the machine is running,
it gets warm to touch and gets hot if you throw a high load at the system, especially if you include storage in the
mix. With the laptop lid closed and the palm rest being present, the cooling situation for this area can be quite bad
indeed. Now that the palm rest is removed, this area of the laptop is now exposed, which should help with the cooling
for this chip.</p>
<p>Having the keyboard connected in this state isn&rsquo;t too bad. It does restrict the airflow a bit, yes, but at least it can
be fastened using two screws, which means that it won&rsquo;t move around and cause any other issues.</p>









<figure class="center">
  <a href="/posts/2023/01/27/thinkpad-as-server-followup/media/image-1.jpg" aria-label="View full-size image">
    <img src="/posts/2023/01/27/thinkpad-as-server-followup/media/image-1_hu_4e06712e1cdb52a4.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>With this setup, the cooling has improved noticeably. Unfortunately it didn&rsquo;t come to my mind to make a before/after
comparison to better illustrate this, so I will just write about how well it operates in this configuration.</p>
<p>Currently, I have the laptop fan controlled by a modified version of <a href="/posts/2022/09/26/minimum-viable-fan-control-script/">the minimum viable fan control script</a>.
The fan only kicks in after the CPU reaches 60°C, ramps up to a moderate speed at over 85°C, and lets the default fan
behaviour handle everything if the temperatures reaches over 95°C. This results in the fan being off completely for most
of the day as the server is idling at around 5-10% CPU usage and temperatures being anywhere between 45-60°C. When there
is a workload on the system that taxes the CPU, the fan will kick on with a small delay.</p>
<p>I&rsquo;ve also disabled turbo boost on the Intel i7-3632QM that is currently in this T430, which limits the clock speed to
2.2 GHz max. Performance takes a small hit, but the CPU is now running much more efficiently. This is one of the tweaks
that allows the laptop to be near silent. At a full 8 thread CPU load using <code>stress -c 8</code>, the CPU core temperatures
peak at 70°C at 22°C ambient temperature, with the fan running at around 2600 RPM.</p>
<p>As a result of all of this, the T430 is very quiet while using about 10-12W of power while idling.
Under the maximum CPU load generated by <code>stress</code>, the total system power usage is around 34W.</p>
<h2 id="putting-the-paste-in-thermal-paste">
  <a class="heading-anchor" href="#putting-the-paste-in-thermal-paste">Putting the &ldquo;paste&rdquo; in thermal paste<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Originally, the T430-as-a-server ran vertically using a basic laptop vertical stand. Back when I concluded the initial
test in 2022, I disassembled the machine and noticed something very odd with the thermal paste.</p>









<figure class="center">
  <a href="/posts/2023/01/27/thinkpad-as-server-followup/media/image-2.jpg" aria-label="View full-size image">
    <img src="/posts/2023/01/27/thinkpad-as-server-followup/media/image-2_hu_b6ce887f6e02fc08.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Based on this image and the fact that I ran the machine quite warm most of the time (CPU temperatures around 60-80°C),
I assume that the excess thermal paste started slowly dripping down. The part that concerns me the most is that the top
of the chip was barely covered by the thermal paste. Either that part of the chip had great contact with the heatsink,
or the thermal paste drooped down with time and left it mostly uncovered. It could explain some of the issues, but
I&rsquo;ll avoid making any definitive conclusions from this alone.</p>
<p>To avoid similar issues in the future, the laptop is now on a stand at about 60° angle. Not sure if it will work,
but it&rsquo;s worth a shot.</p>
<h2 id="closing-thoughts">
  <a class="heading-anchor" href="#closing-thoughts">Closing thoughts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Overall, I&rsquo;m happy with how this experiment turned out. Cooling is no longer an issue, and the T430 that I initially
got for spare parts is actually being useful. The amount of performance this machine offers while using very little
power seems to be a good balance for the workloads that I run on my home server.</p>
]]></content:encoded></item><item><title>I finally found an use case for my Raspberry Pi Model B+</title><link>https://ounapuu.ee/posts/2022/11/01/finding-use-case-for-raspberry-pi/</link><pubDate>Tue, 01 Nov 2022 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/11/01/finding-use-case-for-raspberry-pi/</guid><description>I take a severely underpowered computer and make it do something useful.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="I finally found an use case for my Raspberry Pi Model B+" /><p>You have probably heard about the Raspberry Pi. It&rsquo;s a nice little affordable
single-board computer with a huge community using it for all sorts of projects.</p>
<p>I got my first Raspberry Pi, <a href="https://www.raspberrypi.com/products/raspberry-pi-1-model-b-plus/">the Model B+</a>,
during my first year at university, which was around the winter of 2014/2015.
The idea of a super tiny PC that could actually do useful things was just very
fascinating to me, and I loved the way that green PCB looked.</p>
<p>Over the years, I&rsquo;ve used that Pi and newer revisions of them in all sorts of
use cases: a simple Kodi media box, a Minecraft server, a web server, retro game
emulation box, and much more.</p>
<p>Because the goal of the Raspberry Pi was to be an affordable platform for
experimentation and learning for everyone, they had to keep the costs down. This
meant that the computing power that the Raspberry Pi 1 packed wasn&rsquo;t much.
With the Model B+, you get one ARM CPU core that you can overclock to 1 GHz,
and 512MB of RAM. It wasn&rsquo;t much even at the time of release, and it definitely
isn&rsquo;t great in 2022.</p>
<p>Due to the very limited performance, the use cases for a Raspberry Pi 1 are
quite limited in 2022. Use cases that don&rsquo;t require much computational power
are often better solved by other platforms. Use cases that are actually useful
to me and solve a problem I have are too much for the Pi 1. At the same time,
I absolutely hate it when I have computing equipment sitting around on a shelf
doing nothing. I can&rsquo;t even sell this Pi, because it is not worth much any more
and it has some sentimental value for me.</p>
<p>Taking all that into account, and looking at my parts box, I decided to give one
idea a go: let&rsquo;s build the slowest damn Syncthing backup endpoint imaginable.</p>









<figure class="center">
  <a href="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/0-setup.jpg" aria-label="View full-size image">
    <img src="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/0-setup_hu_1440ba594030c917.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<h2 id="the-build">
  <a class="heading-anchor" href="#the-build">The build<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Here&rsquo;s a quick rundown of the parts:</p>
<ul>
<li>SBC: Raspberry Pi 1 Model B+</li>
<li>Storage (microSD): SanDisk 8GB that I had lying around</li>
<li>Storage (USB): Crucial BX500 1TB SATA 2.5&quot; SSD, in an IcyBox USB-SATA enclosure</li>
<li>Power: official Raspberry Pi microUSB power adapter</li>
<li>Networking: TP-Link TL-WN722N USB WiFI adapter</li>
<li>OS: Raspberry Pi OS 32-bit (lite)</li>
<li>Acoustic foam: yes.</li>
</ul>









<figure class="center">
  <a href="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/1-setup.jpg">
    <img src="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/1-setup_hu_525023390c5fe338.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Alternate angle of the setup.">

  </a>
  <figcaption class="center">Alternate angle of the setup.</figcaption>
</figure>

<p>Use case: networked offsite backup of files that I cannot afford
to lose, powered by <a href="https://syncthing.net/">Syncthing</a>, <code>btrfs</code> as the
filesystem, and <a href="https://digint.ch/btrbk/">btrbk</a> as the snapshotting solution.</p>
<p>I set the OS up using the Raspberry Pi imager due to the useful options it
offered, such as automatically setting my SSH public key authentication up.
Once booted, I logged in and ran <code>sudo apt update -y</code>. I knew what to expect
regarding performance, and was still surprised at how slow things have become.
Updating the system and deploying the configuration using Ansible took hours.</p>
<p>The 1TB SSD is formatted as a <code>btrfs</code> file system and mounted to <code>/storage</code>.
For the Syncthing service, I created a separate user <code>syncthing</code> with the home
folder on <code>/storage/home/syncthing</code>. The synced data will live on <code>/storage/syncthing</code>.
Keeping the home folder on the SSD is intentional: Syncthing keeps track of
application state in a database and storing it on the microSD card will wear it
out much faster. The database can also be quite big if you have a lot of
files to sync.</p>
<p>I&rsquo;m not going to go into the <code>btrbk</code> setup in much detail, but if you&rsquo;re
interested in that, then <a href="/posts/2022/07/09/btrbk-is-awesome/">I do have a write-up about btrbk</a>.
Long story short: snapshots are cool, and they help prevent data loss in case
of accidental deletions.</p>
<p>I set up Syncthing to allow access to the GUI from over the network by changing
the <code>~/.config/syncthing/config.xml</code> file while the service was stopped. Just
change the GUI listen address to <code>0.0.0.0:8384</code>, that will make the GUI accept
connections not only from localhost, but from all machines on the same network.
The next step was to set a password to the GUI and check the &ldquo;Use HTTPS for GUI&rdquo;
box, because you probably don&rsquo;t want any rando messing your machine up.</p>
<p>The choice to go with the WiFi for networking is related to the environment
this system will eventually be deployed to. Ethernet isn&rsquo;t an option there.</p>
<p>Once the system was all set up and files were syncing extremely slowly, I kept
an eye on the Pi, especially the red power LED. I had set the CPU to run at 1 GHz
using <code>raspi-config</code>, and with both the WiFi adapter and SSD connected, I had
concerns that the Pi could not supply enough power. The power limitations of the
Pi are a common source for issues and that has come up in the past as well,
especially with external storage connected to the Pi. However, with this
particular setup this has not been an issue so far. The fact that Pi is so
underpowered that it cannot even make full use of the SSD is probably a
contributing factor to the overall stability.</p>
<p>The file sync was very slow, but at least it was working. The typical transfer
speeds hovered around 1.5 MB/s. Not great, but given the fact that this setup
will operate in an environment where the download speeds are typically capped
around 15-20 Mbit/s, this will be more than enough.</p>









<figure class="center">
  <a href="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/2-htop.png">
    <img src="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/2-htop_hu_5e9fa9e6be7ff6de.webp"
     width="956"
     height="295"
     loading="lazy"
     decoding="async"
     alt="`htop` showing how much the Pi is struggling under operation.">

  </a>
  <figcaption class="center">`htop` showing how much the Pi is struggling under operation.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/3-syncthing.png">
    <img src="/posts/2022/11/01/finding-use-case-for-raspberry-pi/media/3-syncthing_hu_21fd106fb915d1da.webp"
     width="735"
     height="205"
     loading="lazy"
     decoding="async"
     alt="Typical transfer speed that I observed with the setup.">

  </a>
  <figcaption class="center">Typical transfer speed that I observed with the setup.</figcaption>
</figure>

<p>How well will this setup work over a longer time period? Only time will tell.
Just like with <a href="/posts/2021/03/20/whacky-setups-1/">other disastrous tests that I have done</a>,
I&rsquo;ll try to update this post whenever anything noteworthy happens.</p>
<p>Does this setup make any sense if you need a performant Syncthing endpoint?
Hell no. However, I&rsquo;m very happy that this little Pi finally has a purpose.</p>
<h2 id="alternatives">
  <a class="heading-anchor" href="#alternatives">Alternatives<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This project was about finding a purpose for an SBC I already had lying around.</p>
<p><a href="https://www.jeffgeerling.com/blog/2022/you-cant-buy-raspberry-pi-right-now">If the price and availability of Raspberry Pi-s wasn&rsquo;t a complete shitshow in
2022</a>,
I would go for a Raspberry Pi 4 in a heartbeat. I can&rsquo;t, and that makes me
and most of the Raspberry Pi community very sad. The more performant Pi-s open
up so many possibilities.</p>
<p>An <a href="https://orangepi.com/index.php?route=product/product&amp;product_id=846">Orange Pi Zero</a>
running <a href="https://www.armbian.com/orange-pi-zero/">Armbian</a> was something I also
considered, since I had one lying around, but it was a bit too competent for
the job, and I might find a better use for it eventually.</p>
<p>If you wanted performance, then any x86-based PC will do just fine. My
recommendation is to go for an used PC, be it <a href="/posts/2022/05/10/thinkpad-as-a-home-server/">a laptop</a>
or <a href="https://www.servethehome.com/introducing-project-tinyminimicro-home-lab-revolution/">a very small and efficient PC</a>.
Just keep in mind that the power usage is typically higher on these setups
compared to a small ARM-based single-board computer. If a machine runs 24/7, then
the difference between 2-3 W and 10-20 W will start to matter, especially when
energy prices are quite high in your region.</p>
]]></content:encoded></item><item><title>I tried out the CyberPower UT650EG UPS</title><link>https://ounapuu.ee/posts/2022/08/04/cyberpower-ut650eg-overview/</link><pubDate>Thu, 04 Aug 2022 07:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/08/04/cyberpower-ut650eg-overview/</guid><description>Small and very efficient, but not quite ideal for all use cases. At least it hasn't caught on fire yet!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="I tried out the CyberPower UT650EG UPS" /><p>After some spicy feedback to <a href="/posts/2022/05/10/thinkpad-as-a-home-server/">my post where a ThinkPad T430 acted as a server,</a>
I decided to try out one UPS that was recommended on the basis of it being much
more power efficient compared to the APC UPS that I previously ran.</p>
<p>That UPS? <a href="https://www.cyberpower.com/id/en/product/sku/UT650EG">CyberPower UT650EG</a>.</p>









<figure class="center">
  <a href="/posts/2022/08/04/cyberpower-ut650eg-overview/media/image.jpg">
    <img src="/posts/2022/08/04/cyberpower-ut650eg-overview/media/image_hu_114a0a37badbaeb3.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="My ThinkPad-as-a-server, and the UPS that&#39;s powering it.">

  </a>
  <figcaption class="center">My ThinkPad-as-a-server, and the UPS that&#39;s powering it.</figcaption>
</figure>

<h2 id="why-switch-out-a-perfectly-good-ups">
  <a class="heading-anchor" href="#why-switch-out-a-perfectly-good-ups">Why switch out a perfectly good UPS?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The APC Smart-UPS 750 is good, but uses a lot of power compared to the whole setup,
making up roughly half of the total power consumption at idle: ~17-18W. It&rsquo;s
also very big compared to what it is actually powering.</p>
<p>One of the main selling points of this particular CyberPower UPS is that it uses
very little power itself. Depending on the model, the UPS can use around 1-2W
of power, at least according to the tests that they <a href="https://www.cyberpower.com/promotion/ut/id/id">publish on their website</a>.</p>
<p>Once I set up everything with the new UPS, I gave it a go. After the battery was
fully charged, I did observe a dramatic drop in power usage. The whole setup now
ran around 19-21W when idle, which confirms the power consumption numbers
claimed by CyberPower.</p>
<h2 id="overview">
  <a class="heading-anchor" href="#overview">Overview<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The UPS itself is great for someone who just wants to connect a couple of
devices into a standalone UPS. The model I got came with three EU-style sockets.
Compared to the APC UPS, this is a much cleaner setup as I do not have to
connect an extension cord using an adapter.</p>
<p>The APC Smart-UPS 750 can provide anywhere between 100 and 120 minutes of runtime
with my setup. I did a quick runtime test with the CyberPower UPS as well and
found that with around 25W of load it ran for 37 minutes. Not the best runtime,
but given its size it&rsquo;s a respectable result.</p>
<p>Uninterruptible power supplies like to be noisy when running off of batteries.
This CyberPower unit is no exception. However, by letting it run on batteries
and double-clicking the power button I managed to silence the alarm and in
subsequent power cut scenarios it has not started beeping. I was unable to find
a simple manual explaining how to operate the UPS and what other button combos
might be out there. The piece of paper that came with the UPS was also
lackluster. I&rsquo;m not sure if this was intended functionality or not, but I do
like that turning the alarm off is an option in the first place.</p>
<p>The status LED-s on the unit are okay. There aren&rsquo;t many of them and the legend
explaining the behaviour of those lights is just enough to understand what&rsquo;s
going on.</p>
<h2 id="the-not-so-good-parts">
  <a class="heading-anchor" href="#the-not-so-good-parts">The not-so-good parts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This particular unit has an issue. I did a poor job reading the spec sheet at
my local retailer and missed the fact that this specific model does <em>not</em> come
with USB connectivity. If the UPS runs out of power, it cannot warn my server
to shut down in advance, resulting in a dirty shutdown scenario. Given how
stable the power at my apartment generally is, this won&rsquo;t likely be
a major issue, but it&rsquo;s definitely something I miss. The APC UPS supports this,
plus you can log everything about how the batteries are doing and even detect
input voltage anomalies that you probably weren&rsquo;t even aware of.</p>
<p>What I&rsquo;m concerned about is the battery. <a href="https://www.cyberpower.com/id/en/product/sku/UT650EG#specification">The specifications</a>
say that the battery is not user replaceable. I hope that this is simply something
the legal team thought of to avoid any liability when dealing with users who
messed this process up. If not, then it will be a major problem down the line.
Batteries are consumable items, and according to various threads on the web
about UPS batteries, the consensus is that you should replace them every 3-4
years to avoid problems with the batteries swelling up and potentially causing
fires.</p>
<p>If the battery dies and I cannot replace it, then what am I supposed to do,
throw the otherwise functional UPS straight to the landfill? Not acceptable.</p>
<p>Speaking of concerns, I happened to see some
<a href="https://forums.redflagdeals.com/some-cyberpower-upses-may-pose-fire-hazard-2516306/">troubling</a>
<a href="https://www.youtube.com/watch?v=9gqBzLNMFe4">reports</a>
about certain <a href="https://www.reddit.com/r/homelab/comments/voy9kl/cyberpower_cp1500pfclcd_fire_hazard/">CyberPower UPS-es catching on fire.</a>
The culprit seems to be a certain type of glue used in the manufacturing of the
UPS that ends up conducting electricity after a longer time period. I unplugged
my UPS, powered it off and gave it a look, and it seems like I should be fine.
At least I hope so.</p>









<figure class="center">
  <a href="/posts/2022/08/04/cyberpower-ut650eg-overview/media/hopefullynotafirehazard.jpg">
    <img src="/posts/2022/08/04/cyberpower-ut650eg-overview/media/hopefullynotafirehazard_hu_6a24703ac4909581.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Inside of the UPS.">

  </a>
  <figcaption class="center">Inside of the UPS.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2022/08/04/cyberpower-ut650eg-overview/media/inside.jpg">
    <img src="/posts/2022/08/04/cyberpower-ut650eg-overview/media/inside_hu_a98afada1f31cc43.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="I sure hope that this piece of glue won&#39;t burn my house down.">

  </a>
  <figcaption class="center">I sure hope that this piece of glue won&#39;t burn my house down.</figcaption>
</figure>

<p>Based on this view inside the UPS, I feel like changing the battery should at
least be possible, assuming that replacement batteries are readily available.
Just make sure to not touch the rest of the components as they can probably
kill you, and that&rsquo;s just not a fun thing to do.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you want a dumb and efficient UPS that protects you from basic power cutouts
and input voltage changes, then do consider this UPS. However, if you care about
USB connectivity and ease of maintenance, then I recommend looking for other
options.</p>
]]></content:encoded></item><item><title>btrbk is awesome</title><link>https://ounapuu.ee/posts/2022/07/09/btrbk-is-awesome/</link><pubDate>Sat, 09 Jul 2022 16:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/07/09/btrbk-is-awesome/</guid><description>I ramble about a tool that is great for taking regular snapshots on the btrfs filesystem.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="btrbk is awesome" /><p>I like having a safety net whenever I&rsquo;m doing something potentially destructive,
which is why I use the <code>btrfs</code> file system for my operating system and my data.
Snapshots are one half of my &ldquo;whoops, there goes all my work&rdquo; strategy (backups
are the other half).</p>
<p><a href="/posts/2022/04/05/btrfs-snapshots/">I&rsquo;ve written about how I use snapshots on btrfs using snapper,</a>
but lately I&rsquo;ve become annoyed with it.</p>









<figure class="center">
  <a href="/posts/2022/07/09/btrbk-is-awesome/media/image.jpg">
    <img src="/posts/2022/07/09/btrbk-is-awesome/media/image_hu_b045336d02b39269.webp"
     width="1280"
     height="669"
     loading="lazy"
     decoding="async"
     alt="Snapshots: probably invented by a developer who owns a cat.">

  </a>
  <figcaption class="center">Snapshots: probably invented by a developer who owns a cat.</figcaption>
</figure>

<h2 id="shortcomings-of-snapper">
  <a class="heading-anchor" href="#shortcomings-of-snapper">Shortcomings of <code>snapper</code><svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p><code>snapper</code> is great while you&rsquo;re on the happy path, but when you wander off of
it, it gets a bit frustrating. This is 100% my own personal experience and I
cannot rule out any PEBCAK scenarios, but it&rsquo;s how I felt using the tool.</p>
<p>The snapshots are on the same subvolume, such as <code>/home/.snapshots</code>, which means
that I have to specifically exclude the <code>.snapshots</code> folder in every tool and
script that I use for making backups. Without that change, the tools ended up
scanning the folder and eating up a lot of resources, mainly the CPU and storage.</p>
<p>Backing up snapshots to something like an external backup SSD wasn&rsquo;t something
that <code>snapper</code> supported out of the box as well, meaning that for offline
backups I still had to resort to a good old <code>rsync</code> copy. It&rsquo;s inconvenient and
I won&rsquo;t have a backup that also contained recent snapshots, but it was
manageable.</p>
<p>I also reinstalled Fedora Linux on my ThinkPad recently to see how well my
Ansible playbooks hold up (quite decently!) and found that setting up <code>snapper</code>
is a bit of a pain. I tried to set up <code>snapper</code> again, but it wasn&rsquo;t as
straightforward as I was hoping for, with it not properly picking up the
configuration file changes. At the end, it just ran into weird errors
when I tried it to prune some snapshots according to the policy I set up. Since
I was running out of disk space, I just gave up, uninstalled <code>snapper</code> and
destroyed the snapshots manually.</p>
<p>After all that (and a recommendation by a friend) I decided to bite the bullet
and try out <a href="https://github.com/digint/btrbk">btrbk</a>.</p>
<h2 id="btrbk">
  <a class="heading-anchor" href="#btrbk">btrbk<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Setting up <code>btrbk</code> on Fedora Linux 36 was a breeze. Install it via <code>dnf install  btrbk</code>, copy your configuration to <code>/etc/btrbk/</code>, make sure that the directory
used for snapshots exists with <code>mkdir /btrbk_snapshots</code> and you&rsquo;re good to go!
<code>btrbk</code> is just a huge Perl script, so no fancy dependencies are needed.</p>
<p>My <code>btrfs</code> filesystem has three subvolumes: <code>/</code>, <code>/home</code> and <code>/storage</code>. Data
stored on these subvolumes has different levels of importance, which is also
reflected in the snapshot retention policies.</p>
<p>The configuration on my setup is the following:</p>
<pre tabindex="0"><code>timestamp_format        long

volume /
  snapshot_dir /btrbk_snapshots
  subvolume /
    snapshot_preserve_min   12h
    snapshot_preserve       24h
  subvolume /home
    snapshot_preserve_min   48h
    snapshot_preserve       7d
  subvolume /storage
    snapshot_preserve_min   6h
    snapshot_preserve       7d
</code></pre><p>To take the snapshots, I&rsquo;ve set up a systemd timer that runs every 5 minutes and
runs the following command:</p>
<pre tabindex="0"><code>btrbk -c /etc/btrbk/btrbk.conf run --progress
</code></pre><p>A successful run will have output like this:</p>
<pre tabindex="0"><code>--------------------------------------------------------------------------------
Backup Summary (btrbk command line client, version 0.32.1)
    Date:   Sat Jul  9 14:00:00 2022
    Config: /etc/btrbk/btrbk.conf
Legend:
    ===  up-to-date subvolume (source snapshot)
    +++  created subvolume (source snapshot)
    ---  deleted subvolume
    ***  received subvolume (non-incremental)
    &gt;&gt;&gt;  received subvolume (incremental)
--------------------------------------------------------------------------------
/
+++ /btrbk_snapshots/ROOT.20220709T1400
--- /btrbk_snapshots/ROOT.20220708T1300
/home
+++ /btrbk_snapshots/home.20220709T1400
/storage
+++ /btrbk_snapshots/storage.20220709T1400
--- /btrbk_snapshots/storage.20220709T0745
--- /btrbk_snapshots/storage.20220709T0750
--- /btrbk_snapshots/storage.20220709T0755
</code></pre><p>I love how the output is very concise about what it just did.</p>
<p>To make a backup of my drive to an external SSD that&rsquo;s also a <code>btrfs</code> filesystem,
I created a separate config at <code>/etc/btrbk/backup-to-ext-drive.conf</code>:</p>
<pre tabindex="0"><code>timestamp_format        long

target_preserve_min    no
target_preserve        7d

volume /
  snapshot_dir /btrbk_snapshots
  target /mnt/backup/T430
  subvolume /
  subvolume /home
  subvolume /storage
</code></pre><p>In this example, <code>/mnt/backup/T430</code> is a <code>btrfs</code> subvolume itself.</p>
<p>Instead of running <code>rsync</code>, my backup script contains the line:</p>
<pre tabindex="0"><code>btrbk -c /etc/btrbk/backup-to-ext-drive.conf run --progress
</code></pre><p>I love how the default behaviour in <code>btrbk</code> is to keep snapshots separate from
the subvolumes themselves. Making a full copy of <code>/home</code> or any other filesystem
doesn&rsquo;t require me to always exclude the <code>.snapshots</code> directory, which is nice.</p>
<p>The snapshot names themselves are also human readable. If I accidentally messed
up and my changes from an hour ago were lost, I&rsquo;d just have to go to
<code>/btrbk_snapshots</code>, look up a snapshot from an hour ago, and copy whatever I
need from the snapshot. This has already saved my butt at least once.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s not often that a piece of software gets me that excited, but <code>btrbk</code> has
somehow managed to do it. It&rsquo;s a single script that has all the example use
cases documented in its README and the functionality does exactly what I want.</p>
<p>That&rsquo;s all I really need from software.</p>
<p>Huge thanks to <a href="https://digint.ch/">Digital Integrity GmbH</a> for building,
maintaining and sharing this tool with the world!</p>
]]></content:encoded></item><item><title>Can a laptop from 2012 be a viable home server?</title><link>https://ounapuu.ee/posts/2022/05/10/thinkpad-as-a-home-server/</link><pubDate>Tue, 10 May 2022 09:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/05/10/thinkpad-as-a-home-server/</guid><description>I took a spare ThinkPad T430 and put all my home server workloads on it. Here's how it went.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Can a laptop from 2012 be a viable home server?" /><p>I&rsquo;m a man of many ideas. It&rsquo;s a shame that most of them are quite stupid.</p>
<p>This is one of them, but at least it makes for a fun experiment.</p>
<h2 id="intro">
  <a class="heading-anchor" href="#intro">Intro<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>After <a href="/posts/2022/03/21/ups-i-did-it-again/">adding an UPS to accompany my server,</a>
my setup was as complete as it could reasonably be. The server is low power,
but packs quite a punch with fast storage and plenty of compute power around.
The UPS provides a battery backup for both my server and the router.</p>
<p>There was still one annoyance lingering at the back of my head: this setup took
40 watts of power in idle. That&rsquo;s a lot for something that runs 24/7. Yes,
<a href="https://www.reddit.com/r/homelab/">/r/homelab</a> regularly showcases more
power hungry setups, but my standards are quite high when it comes to power use.
I want to go as low as reasonably possible.</p>
<p>I recently bought a spare ThinkPad T430 so that I can have a backup machine in case
something happens to <a href="/posts/2022/01/09/why-i-went-back-to-using-a-thinkpad-from-2012/">my laptop that doesn&rsquo;t suck</a>.
I&rsquo;ve also <a href="/posts/2020/08/22/stupid-project-ideas-1/">had ideas about a server setup involving this laptop.</a></p>
<p>That&rsquo;s when I decided to try running my services off of the ThinkPad T430.</p>









<figure class="center">
  <a href="/posts/2022/05/10/thinkpad-as-a-home-server/media/image1.jpg">
    <img src="/posts/2022/05/10/thinkpad-as-a-home-server/media/image1_hu_60bcdba190871e52.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The setup.">

  </a>
  <figcaption class="center">The setup.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2022/05/10/thinkpad-as-a-home-server/media/image2.jpg">
    <img src="/posts/2022/05/10/thinkpad-as-a-home-server/media/image2_hu_fa9f5efc5d128f8b.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Another angle of the setup.">

  </a>
  <figcaption class="center">Another angle of the setup.</figcaption>
</figure>

<h2 id="the-setup">
  <a class="heading-anchor" href="#the-setup">The setup<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Here&rsquo;s a quick rundown of the relevant specifications:</p>
<ul>
<li>CPU: Intel i5-3320M, 2 cores 4 threads @ 3.3GHz max</li>
<li>RAM: 16GB DDR3</li>
<li>OS disk: 256GB Micron mSATA SSD</li>
<li>Main storage: 2x 4TB Samsung 870 QVO SSD</li>
</ul>
<p>One of the main reasons that this setup is viable in the first place is the fact
that the ThinkPad T430 supports up to 3 SSD-s if you replace the optical drive
with a HDD caddy. Your OS can run off of an mSATA SSD and your mirrored storage
can utilize the two 2.5&quot; SATA slots.</p>
<p>You probably don&rsquo;t want to use a setup like this if you want to store a lot of
big files, such as your legally obtained media collection. If your data can fit
on a pair of SATA SSD-s, then this setup will be just fine.</p>
<h2 id="why-use-a-laptop-as-a-home-server">
  <a class="heading-anchor" href="#why-use-a-laptop-as-a-home-server">Why use a laptop as a home server?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you don&rsquo;t have a home server yet and want to start off as cheap as possible
while also being mindful of the power usage, then an used laptop with a competent
CPU is a fantastic starting point. In an age where 6 CPU cores is considered
mid-range, two CPU cores might not sound like much, but for most home server
workloads it&rsquo;s absolutely fine.</p>
<p>Laptop CPU-s are designed to use as little power as possible. After all, they
need to run off of a small battery most of the time and have to run cool as well
to make do with the limited cooling setup that they have. This makes them ideal
for a machine that runs 24/7.</p>
<p>I measured the power usage of my ThinkPad T430 in this configuration and found
that it used around 15-20 watts when running with a low load. This is comparable
to the <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">ASRock DeskMini X300</a>.</p>
<p>What sets laptops apart from the usual desktop-based home server builds is that
they often have a working battery, which can act as a poor man&rsquo;s UPS. If you
momentarily lose power, then the server will happily keep on working until the
battery runs out, which might take 1-2 hours (or more if your battery is in a
good state). This is comparable to the runtime I saw with the DeskMini server
build and the APC Smart-UPS 750.</p>
<p>Most laptops also come with an Ethernet port, and if the laptop is made some
time after 2005, then it&rsquo;s likely running at gigabit speeds. Unless you have a
valid use case for 10 gigabits or more, then this will be plenty of network
bandwidth for most home server use cases.</p>
<p>One aspect that&rsquo;s often overlooked with a laptop-based home server setup is the
inclusion of an integrated keyboard and mouse. If you accidentally mess up your
configuration and your server does not start up properly, then you can just open
the lid and start fixing it on the spot. On any other setup, you&rsquo;d have to find
a monitor to hook the server up to and find a spare keyboard to use as well,
which can be a hassle.</p>
<h2 id="performance">
  <a class="heading-anchor" href="#performance">Performance<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>A home server that serves the needs of a couple of users at most and runs some
scheduled tasks from time to time can run perfectly fine off of a dual core
Intel Core series CPU from 2012. You probably don&rsquo;t want to run intensive
computational workloads off of it, such as transcoding video files on a service
like Jellyfin. However, you can utilize the integrated GPU to off-load specific
workloads to it, and media encode-decode for select video codecs is one of those.
Intel QuickSync is an absolute godsend for situations where you need to transcode
media on a CPU that isn&rsquo;t that powerful.</p>
<p>My home server runs a lot of services: Docker containers, this blog, data archival
jobs, backup jobs etc. When running them on the T430, the average CPU usage was
around 20%. Not ideal, but still leaves plenty of headroom for services.</p>
<p>The overall usability and performance that this machine offers was completely
acceptable. It&rsquo;s not as lightning fast as something that runs a modern CPU,
like the AMD Ryzen 5 PRO 4650G in the DeskMini, but it gets the job done.</p>
<h2 id="caveats-thermals">
  <a class="heading-anchor" href="#caveats-thermals">Caveats: thermals<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>A home server built around a used laptop brings a lot of benefits. However,
it also has some potential downsides that you should be aware of.</p>
<p>Most laptops have fans, and they can be damn loud. The ThinkPad T430 is
notoriously loud if you have the cooling fan manufactured by Toshiba. In a home
setting this can potentially a deal-breaker, unless you can wedge the laptop
into a corner of the room where it&rsquo;s not audible.</p>
<p>There exist solutions to the fan control problem. You can install a tool like
thinkfan or just write your preferred fan level to <code>/proc/acpi/ibm/fan</code> to
avoid the cooling fan running too loud <a href="https://wiki.archlinux.org/title/fan_speed_control#ThinkPad_laptops">(instructions here)</a>.</p>
<p>Running the fan at the lowest speed works fine most of the time since your CPU
can throttle itself when it&rsquo;s running too hot. However, with my setup I had an
odd issue where the machine would power off suddenly when it was doing a lot of
I/O workload, such as scrubbing the ZFS pool on the two 4TB SSD-s. This happened
even when the CPU was not even close to throttling, running around 75 C. I do
not know what the actual reason for the sudden shutdown is, but I suspect that
it may be related to the motherboard overheating or the system treating the hot
SSD-s as hard drives that are over the critical temperature limit of around 60 C.</p>
<p>I was able to work around most of the cooling-related issues by mounting the
laptop vertically and limiting the maximum CPU clock speed to around 2.4 GHz
using the knobs made available with <code>intel_pstate</code>.</p>
<p>The CPU temperatures during normal operation were mostly around 60C, with a high
load reaching max 75C with the tweaks applied and the CPU fan running at the
slowest possible speed.</p>
<h2 id="caveats-maintenance">
  <a class="heading-anchor" href="#caveats-maintenance">Caveats: maintenance<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you have a machine that runs 24/7, maintenance will become an issue. No
matter how often you clean your home, dust will accumulate. On desktop PC-s,
cleaning out your CPU heatsink is just a matter of taking off the PC case side
panel, removing the heatsink fan, cleaning off the dust and putting it all back
together. You probably want to replace the thermal paste from time to time as
well.</p>
<p>On most laptops, cleaning out the CPU heatsink is much trickier. You will likely
have to disassemble most of the machine to even access it, which takes up much
more time compared to a desktop PC, which also means more downtime.</p>
<p>Depending on the model, a simple change, such as upgrading your storage or
replacing a faulty drive, can also be more complicated. I&rsquo;ve seen laptops where
you actually have to disassemble the whole machine to access the hard drive.
The ThinkPad T430 has an easily accessible setup when it comes to storage, but
the main storage bay does have an annoying pull-tab setup that probably won&rsquo;t
survive multiple subsequent changes.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Aside from the setbacks that may or may not be due to the specifics of my setup,
I find that a laptop can make for a good home server. If you have more specific
requirements, then a custom-built server is likely the way to go, but if you&rsquo;re
just starting out, then definitely do consider this option.</p>
<p>After running this setup for a week or two, I decided to go back to my previous
setup based on the ASRock DeskMini. The reliability woes weren&rsquo;t something I
was too happy with, and I didn&rsquo;t really have another use case for the DeskMini
either, so it made sense for me.</p>
]]></content:encoded></item><item><title>My self-hosting setup has an UPS now, here's my experience with it</title><link>https://ounapuu.ee/posts/2022/03/21/ups-i-did-it-again/</link><pubDate>Mon, 21 Mar 2022 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/03/21/ups-i-did-it-again/</guid><description>UPS, I did it again 🎵</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="My self-hosting setup has an UPS now, here's my experience with it" /><p>I changed my setup again.</p>
<p>I&rsquo;m now the proud owner of an APC Smart-UPS 750.</p>









<figure class="center">
  <a href="/posts/2022/03/21/ups-i-did-it-again/media/ups.jpg">
    <img src="/posts/2022/03/21/ups-i-did-it-again/media/ups_hu_8b82e70f8d835724.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The UPS is many times larger than the actual server.">

  </a>
  <figcaption class="center">The UPS is many times larger than the actual server.</figcaption>
</figure>

<p>Why? Because I got it as a gift, and I have never actually had an UPS before, so
it makes for a good introduction to this world.</p>
<h2 id="overview">
  <a class="heading-anchor" href="#overview">Overview<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My setup is quite basic: everything that I have on my table (server, monitor,
laptop) is connected through the UPS. Since my setup uses very little power,
I&rsquo;m running way below the output limit of 500 watts.</p>
<p>When I&rsquo;m not using my laptop, the UPS reports itself at 10% utilization. My
server and the UPS itself seems to consume around 35-40 watts, as measured by
an energy meter. When the laptop and monitor are also powered on, the load is
around 15-25%, depending on the workload.</p>
<p>To make sure that I get the full benefit of the UPS, I connected it to my server
with an USB cable and installed <code>apcupsd</code>. By default, the daemon could not
detect the UPS, which was then fixed with the help of <a href="https://unix.stackexchange.com/a/538636">this StackExchange answer</a>:</p>
<blockquote>
<p>I had the same problem with COMMLOST with a USB connection, after a lot of
research I found by pure hazard that with a USB connection you should change
DEVICE /dev/ttys0 to DEVICE in /etc/apcupsd/apcupsd.conf with nothing after it,
this way apcupsd search everywhere on the system to find the UPS and connect
correctly, no more COMMLOST.</p>
<p>After that, restart apcupsd with:</p>
<p>$ sudo /etc/init.d/apcupsd restart</p>
</blockquote>
<p>With the UPS connected and the service up and running, I could now see more
detailed specs. The output for <code>apcaccess</code> looks something like this:</p>
<pre tabindex="0"><code>APC      : 001,043,1007
DATE     : 2022-02-04 21:49:08 +0200  
HOSTNAME : deskmini
VERSION  : 3.14.14 (31 May 2016) debian
UPSNAME  : deskmini
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2022-02-01 05:45:50 +0200  
MODEL    : Smart-UPS 750 
STATUS   : ONLINE 
LINEV    : 241.9 Volts
LOADPCT  : 9.1 Percent
BCHARGE  : 100.0 Percent
TIMELEFT : 98.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
OUTPUTV  : 241.9 Volts
SENSE    : High
DWAKE    : -1 Seconds
DSHUTD   : 90 Seconds
LOTRANS  : 208.0 Volts
HITRANS  : 253.0 Volts
RETPCT   : 0.0 Percent
ITEMP    : 33.3 C
ALARMDEL : 30 Seconds
BATTV    : 27.4 Volts
LINEFREQ : 50.0 Hz
LASTXFER : No transfers since turnon
NUMXFERS : 0
TONBATT  : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
SELFTEST : NO
STESTI   : 14 days
STATFLAG : 0x05000008
MANDATE  : 2007-03-16
SERIALNO : &lt; serial number goes here &gt;
BATTDATE : 2007-03-16
NOMOUTV  : 230 Volts
NOMBATTV : 24.0 Volts
FIRMWARE : 651.13.I USB FW:7.3
END APC  : 2022-02-04 21:49:10 +0200  
</code></pre><p>I&rsquo;ve seen some unintentionally funny abbreviations, but <code>CUMONBATT</code> takes the
cake.</p>
<h2 id="battery-runtime-test">
  <a class="heading-anchor" href="#battery-runtime-test">Battery runtime test<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>To test out the state of the batteries and understand how the UPS handles power
failure scenarios, I decided to pull the plug and see what happens next.</p>
<p>The first thing you&rsquo;ll notice is the beeping. It&rsquo;s not quite as loud as a smoke
detector, but I couldn&rsquo;t blame my neighbours for thinking that this was the case.
To silence the UPS, just press the power on/test button (the one with the | on
it).</p>
<p>While on batteries, the UPS emits a hum that&rsquo;s not too different from the one
present near some power stations and transformers. Other than that, it doesn&rsquo;t
get awfully loud or anything, at least on a small load.</p>
<p>I continued using my laptop and monitor while keeping an eye on the <code>apcupsd</code>
daemon and <code>apcaccess</code> output. The estimated runtime was around the 60 minute
mark and it ended up being quite close to the actual figure.</p>
<p>Around the 10% capacity mark <code>apcupsd</code> triggered a shutdown of the server. The
UPS still provided power at that point. I decided to supply the UPS with power
again and turn on my server. To my surprise, the UPS now cut off all output
power and started blinking some lights, one of them indicating some sort of an
issue with the battery. I turned everything off, then on again and the UPS was
just fine.</p>
<p>I&rsquo;m not sure if the last incident was intended behaviour or my inexperience
causing an issue.</p>
<h2 id="power-usage">
  <a class="heading-anchor" href="#power-usage">Power usage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The goal of <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">moving my setup to an efficient machine</a>
was to experiment with how low can I go with the power usage of my setup.
Unfortunately with the introduction of the UPS I have wiped out almost all of
the gains that I got from the move. The UPS itself seems to constantly consume
around 17-18 watts, which is just a bit more than my server itself is using.</p>
<p>However, I hope that the reliability improvements and various protections
that come with the use of an UPS make up for that downside.</p>
<h2 id="lan-resilience">
  <a class="heading-anchor" href="#lan-resilience">LAN resilience<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With the initial setup that I had, the server and the UPS were both on my desk.
In the event of a power outage, the server, my laptop and all the connected
peripherals would continue working. The only issue is that the networking won&rsquo;t
work in such a scenario, as both the ISP provided modem-router box and my own
router would be knocked offline. What use is a server disconnected from the
network?</p>
<p>Since I use my laptop for work, I&rsquo;m not too worried about it losing power.
Laptops have batteries, so in the event of a power outage, it will just continue
running off of the internal battery.</p>
<p>I&rsquo;ve configured my router to resolve my own domains internally, meaning that even
when I cannot connect to the Internet, my locally hosted services will keep
working in some capacity.</p>
<p>With all of this in mind, I decided to move my setup closer to my main router.</p>









<figure class="center">
  <a href="/posts/2022/03/21/ups-i-did-it-again/media/newsetup.jpg">
    <img src="/posts/2022/03/21/ups-i-did-it-again/media/newsetup_hu_6a26e086f041e5f1.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Not the prettiest setup, but it does do the trick, and it makes for a good conversation starter.">

  </a>
  <figcaption class="center">Not the prettiest setup, but it does do the trick, and it makes for a good conversation starter.</figcaption>
</figure>

<p>Power goes out, my server and local network will still keep on working for up to
2 hours due to the low combined power usage.</p>
<h2 id="desktop-integration">
  <a class="heading-anchor" href="#desktop-integration">Desktop integration<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>When testing the UPS on my main workstation (ThinkPad T430 running Fedora 35), I
was positively surprised by the out of the box experience that I had with the
UPS. With the USB cable connected to the laptop and the <code>apcupsd</code> service
running in the background, I could see the remaining battery life of the UPS the
same way that the laptop battery shows up.</p>









<figure class="center">
  <a href="/posts/2022/03/21/ups-i-did-it-again/media/gnome-power-info.png">
    <img src="/posts/2022/03/21/ups-i-did-it-again/media/gnome-power-info_hu_347b5c3294d0c6ea.webp"
     width="718"
     height="265"
     loading="lazy"
     decoding="async"
     alt="The UPS showing up as the main battery in GNOME 41.">

  </a>
  <figcaption class="center">The UPS showing up as the main battery in GNOME 41.</figcaption>
</figure>

<p>And once I ran out the batteries, I got a notification saying that the UPS was
about to run out of power soon.</p>









<figure class="center">
  <a href="/posts/2022/03/21/ups-i-did-it-again/media/gnome-ups-warning.png">
    <img src="/posts/2022/03/21/ups-i-did-it-again/media/gnome-ups-warning_hu_3462b75ba9ef5f21.webp"
     width="508"
     height="106"
     loading="lazy"
     decoding="async"
     alt="Warning notification that pops up once the UPS is running low on power.">

  </a>
  <figcaption class="center">Warning notification that pops up once the UPS is running low on power.</figcaption>
</figure>

<p>I love seeing these relatively niche use cases supported out of the box. Props
to the developers behind these quality of life improvements!</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Would I have gone out and bought this UPS if I didn&rsquo;t receive it as a gift?
Probably not, because I didn&rsquo;t see much of a need for one.</p>
<p>Now that I have it, will I keep using it? Definitely, assuming that the
inevitable battery replacement cost is reasonable and the process of changing
them is easy enough for an enthusiast to handle.</p>
<p>From the manual:</p>
<blockquote>
<p>For Professional Business Applications – Not For Consumer Use</p>
</blockquote>
<p>Look, ma, I&rsquo;m a professional now!</p>
]]></content:encoded></item><item><title>How I treat my urge to hoard data</title><link>https://ounapuu.ee/posts/2022/03/08/something-is-better-than-nothing/</link><pubDate>Tue, 08 Mar 2022 07:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/03/08/something-is-better-than-nothing/</guid><description>Something is better than nothing.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="How I treat my urge to hoard data" /><p>The tagline for <a href="https://www.reddit.com/r/DataHoarder/">/r/datahoarder</a> reads:
&ldquo;It&rsquo;s A Digital Disease!&rdquo;. I agree.</p>









<figure class="center">
  <a href="/posts/2022/03/08/something-is-better-than-nothing/media/why-cant-i-hold-all-these-drives.jpg">
    <img src="/posts/2022/03/08/something-is-better-than-nothing/media/why-cant-i-hold-all-these-drives_hu_5e93fb29edda7513.webp"
     width="458"
     height="449"
     loading="lazy"
     decoding="async"
     alt="Why can&#39;t I hold all these hard drives?">

  </a>
  <figcaption class="center">Why can&#39;t I hold all these hard drives?</figcaption>
</figure>

<p>At some point I realized that the pursuit to hoard all the things will just keep
on consuming more and more of my time and money. Storage is cheap up until to a
point, once you find yourself tracking hard drive prices via
<a href="https://de.camelcamelcamel.com">camelcamelcamel</a> and being excited that a 12 TB
external hard drive is at it&rsquo;s lowest price, you may start suspecting that you
have a hoarding issue.</p>
<p>I don&rsquo;t have anything against what people at /r/datahoarder and other archival
efforts do. Data archival done by volunteers is what allows us to preserve
history and cultural artifacts of our time (YouTube videos, memes etc.). I just
had to find a solution to my situation before it got too bad.</p>
<h2 id="something-is-better-than-nothing">
  <a class="heading-anchor" href="#something-is-better-than-nothing">Something is better than nothing<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Once you find yourself with terabytes of data and decide to scale down, you will
need to make some changes. Most of the time this results in deleting a lot of
data that you don&rsquo;t care about that much. This works, but there are some files
that will be difficult to part with.</p>
<p>In my experience, most of the storage is taken up by media files.
I would still like to have a copy of some videos, but if they are downloaded
in 1080p or 4K resolutions, they will take up a lot of space.</p>
<p>That&rsquo;s when I decided to change my approach with data like that. I would still
like to have <em>a</em> copy, but it doesn&rsquo;t necessarily have to be full quality all
the time. When you rewatch YouTube videos that you have archived from 2006-2010s,
you&rsquo;ll notice that the video quality is bad. That doesn&rsquo;t mean that you enjoy
the videos any less. Watching these old videos is just an act of going through
your memories and feeling nostalgic, the medium itself is just the spark needed
to revive the memories.</p>
<p>With that, I decided to start following this simple rule: <em>something is better
than nothing</em>.</p>
<p>I don&rsquo;t need 4K versions of all the channels I follow. <code>bestvideo[height&lt;=1080]</code>
in <code>yt-dlp</code> configuration will limit the resolution of all the videos you download
to 1080p, which is still good enough.</p>
<h2 id="data-value-and-you">
  <a class="heading-anchor" href="#data-value-and-you">Data, value, and you<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you&rsquo;re someone like me who watches YouTube frequently, then you probably have
some channels that you care about a lot.</p>
<p>With channels that I truly care about, I still keep the highest quality copies of
all their videos on my server. This has a real cost in terms of storage, but the
value I have got out of the videos is much greater than that.</p>
<p>However, there are some exceptions. <a href="https://www.youtube.com/c/LinusTechTips">LinusTechTips</a>
is a great channel and has had a huge influence in my life. However, they upload
almost daily and do long streams from time to time. Archiving the whole channel
is just not feasible at my scale. Even when limiting the resolution to 480p,
the full channel archive takes up over 300 GB of space in 2022. Instead, I&rsquo;ve
opted to recognizing the videos that are the most memorable, such as
<a href="https://youtu.be/eCz-IixxR_k">the petabyte project</a>, and have archived those
individually.</p>
<p>There&rsquo;s also a certain type of data that isn&rsquo;t that common: data created by you
and your friends/family. Extra care and focus should be put on this type of
data, because it&rsquo;s very unlikely that someone else has a copy of gigabytes worth
of cat pictures you&rsquo;ve taken over the years. Make plenty of backups and don&rsquo;t
worry too much about hoarding it now, as long as it&rsquo;s not a big burden for you.</p>
<h2 id="constraints">
  <a class="heading-anchor" href="#constraints">Constraints<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Constraints force you to get creative. It also helps with tuning down your data
hoarding habit.</p>
<p>Set physical limitations to the data you can store. For example: limit yourself
to running only two hard drives at a time. The only way to get more storage is
to upgrade vertically to bigger hard drives, which is naturally
throttled by the relatively slow increases in hard drive sizes.</p>
<p><a href="/posts/2022/01/17/asrock-x300-future-of-desktops/">For reference, my current setup has some pretty harsh limits when it comes to
storage</a>. The only way to get
more is to spend a lot of money on bigger SSD-s.</p>
<h2 id="the-internet-archive">
  <a class="heading-anchor" href="#the-internet-archive">The Internet Archive<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you don&rsquo;t want to go through all the hassle, but still want to contribute
to archival efforts, then you can donate to <a href="https://archive.org/donate/">the Internet Archive</a>
instead. Buying and running all those hard drives isn&rsquo;t free, you know.</p>
<p>And if you&rsquo;re planning on uploading data to the Internet Archive, then please
do not abuse it. Only upload data that you feel is worth preserving.</p>
]]></content:encoded></item><item><title>Surviving the front page of HackerNews on a 50 Mbps uplink</title><link>https://ounapuu.ee/posts/2022/02/09/hn-stats-analytics/</link><pubDate>Wed, 09 Feb 2022 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/02/09/hn-stats-analytics/</guid><description>Overview of basic analytics during that one time my blog post got traction on HackerNews, and the steps I took to prepare for just this occasion.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Surviving the front page of HackerNews on a 50 Mbps uplink" /><p>Around a month ago <a href="https://news.ycombinator.com/item?id=29871693">I shared my blog post</a>
on HackerNews. I guess I lucked out with the choice of the topic, because it
brought out a lot of enthusiasts who shared their own experiences with older
machinery that still works in 2022. I really appreciate the feedback and the
experiences shared!</p>
<p>Anyway, what is noteworthy in my opinion is that my blog runs off of a residential
connection that has an upload speed limit of 50 Mbps. Once I noticed the post
getting traction, I was worried for a moment. It&rsquo;s not a rare sight to see a post
on the front page of HackerNews and see it being down due to all the attention
it got.</p>
<p>Somehow, my post managed to weather the storm. Here&rsquo;s what happened.</p>
<h2 id="analyzing-the-logs">
  <a class="heading-anchor" href="#analyzing-the-logs">Analyzing the logs<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My page doesn&rsquo;t have any sort of first-party or third-party analytics software
running. Tracking users across the web is a big no-go for me and I will live by
that, especially on my website. I do have <code>nginx</code> logs, though.</p>
<p>After a quick look around, I found <code>goaccess</code>, a tool that can parse <code>nginx</code>
logs and put together some basic statistics. I found it to be good enough for my
purposes. Here are some notable statistics.</p>
<p>To understand the HackerNews effect, note that the post was published on
2022-01-10 07:42. These logs also include requests towards services that I host
myself.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/0-summary.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/0-summary_hu_b474c8c8793657ee.webp"
     width="765"
     height="129"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>The summary of the week during which one of my posts got popular on HN, as
reported by <code>goaccess</code>, looks like this.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/1-unique-visitors.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/1-unique-visitors_hu_49ff5e1446f00055.webp"
     width="422"
     height="236"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>During quiet days, nginx logs around 50K requests a day. On 10th of January,
there was a 12x increase. The effect was also noticeable the next day, during
which I assume people caught up with their 100+ tabs that they usually have
open. This may also be down to the post being shared around as well.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/2-requested-files.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/2-requested-files_hu_39a135548114515b.webp"
     width="1182"
     height="573"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>Based on this statistic, it seems that the post got around 75K views, either by
real people, crawlers or preview generators.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/3-static-requests.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/3-static-requests_hu_ffdb322a95f80571.webp"
     width="1006"
     height="575"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>When we look at the number of requests made towards specific assets, such as
the images in the post, we can see that real impressions are likely to be
around 55K. The first image has been downloaded more than the other two, likely
indicating that it was used as the preview image when the article was linked
on other sites.</p>
<p>This statistic also highlights a surprisingly large cost of web fonts.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/6-operating-systems.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/6-operating-systems_hu_39d29d88d2748f31.webp"
     width="391"
     height="213"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>The OS results are likely to be biased, since my self-hosted services go through
the same reverse proxy. The &ldquo;Unknown&rdquo; section is likely related to crawlers and
other bots pinging my server.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/7-browsers.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/7-browsers_hu_2c11e077a3bee02.webp"
     width="382"
     height="211"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>No surprise there: Chrome is the most popular browser used to reach my site.
Firefox makes up a good chunk of hits as well, but a lot of those are likely
requests made from my own machine.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/8-time-distribution.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/8-time-distribution_hu_ac0137243e7e9ac.webp"
     width="1280"
     height="355"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>The time distribution of the requests is interesting. You can notice the background
noise associated with bots and crawlers that occurs during the night. My post
was posted in the morning in my local timezone (UTC +2), which was around the
time EU people wake up and get to work. The other spike around 14-15:00 can
likely be attributed to our friends over the Atlantic ocean.</p>
<p>16:00 in my local time is a bit special. A lot of things coincide with this time:</p>
<ul>
<li>the review embargo for the latest highly sought after CPU/GPU is over, followed
by a barrage of videos on this product in YouTube</li>
<li>the stock market opens and news start rolling in about some big moves</li>
<li>if Slack is having issues, then it&rsquo;s around this time, because I can only
assume that people get to work and do a production release at the start of the
workday.</li>
</ul>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/13-http-status-codes.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/13-http-status-codes_hu_cab75752f718d089.webp"
     width="901"
     height="503"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>To my surprise, my server survived this and there aren&rsquo;t too many issues. The
400 and 500 errors are likely attributed to bots trying to exploit my server and
crawlers visiting links that are not valid any more.</p>









<figure class="center">
  <a href="/posts/2022/02/09/hn-stats-analytics/media/16-geolocation.png" aria-label="View full-size image">
    <img src="/posts/2022/02/09/hn-stats-analytics/media/16-geolocation_hu_1178a8ef5d7702d0.webp"
     width="467"
     height="220"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p>There&rsquo;s likely a bias here as well regarding Europe.</p>
<h2 id="how-i-built-the-blog">
  <a class="heading-anchor" href="#how-i-built-the-blog">How I built the blog<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>When I started writing blog posts regularly, I had some principles that I wanted
to stick to:</p>
<ul>
<li>the goal should be on the writing, not the part where I build the website itself</li>
<li>the site has to be static: build it once and deploy it, which should result in
fewer opportunities for attacks and reduced load on the CPU</li>
</ul>
<p>With this in mind, I decided to stick with <a href="https://gohugo.io/">Hugo</a>. Hugo is
just a single binary, has plenty of themes to pick from, and it seems like a
reasonable-enough choice for a site. It&rsquo;s not the easiest to use as you&rsquo;ll be
mainly operating in Markdown, and with the theme that I use, I have to
copy-paste a <code>&lt;figure&gt;</code> section, change the image name that it points to, and
make sure that I didn&rsquo;t mess anything up. However, because this approach rules
out me getting hit by the hottest Wordpress plugin vulnerability of the week, I
think it&rsquo;s a fair trade-off to make.</p>
<p>I picked <a href="https://github.com/panr/hugo-theme-hello-friend">this theme</a> by
<a href="https://radoslawkoziel.pl/">Radosław Kozieł</a> and customized it so that it has a landing page
of sorts as well. I haven&rsquo;t updated it yet and it has some flaws, but it gets
the job done, and that&rsquo;s what matters to me the most.</p>
<p>Hosting media, such as images, seems like a no-brainer, just put them on the
page and be done with it. Pictures taken with an iPhone SE 2020 are quite big,
though (3-4 MB per image), which will result in the page loading very slowly.
To avoid images bloating the size of the page too much, I have set up a system
where I keep the original images in one folder, copy them to another one, run
<code>mogrify -resize 1024x768 -quality 85 *.jpg</code> to keep the images small, but still
detailed enough, and then deploy those converted images along with the rest of
the blog.</p>
<p>With converted images, a page with three images can fit in less than 1 MB of
transferred files without any issues. With original images, the same page would
require 10 MB of files to be transferred. The math is simple: with a limited
uplink, optimizing the images results in your server being able to serve 10x
more requests.</p>
<h2 id="residential-connections-and-dns">
  <a class="heading-anchor" href="#residential-connections-and-dns">Residential connections and DNS<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you&rsquo;re like me, then you probably have a crappy router/modem box from your
local ISP, and a dynamic IP address that usually changes whenever you reboot
said box. This presents a challenge when you try to host anything from your
residential connection since the IP address could change at any time.</p>
<p>To resolve this, there are two options I&rsquo;m aware of: dynamic DNS providers, or
setting up a script that talks to your DNS provider over a standard API.</p>
<p>I haven&rsquo;t personally used any dynamic DNS providers, such as <a href="https://www.duckdns.org">DuckDNS</a>,
mainly because my domain registrar has a handy API that I can use to
automatically update my IP address with any time it changes. And yes, I did have
an issue with the script where I triggered a change every minute, resulting in
an angry e-mail being sent to me. Free tech tip: only propagate changes when the
IP address <em>actually</em> changes.</p>
<p>There&rsquo;s one downside with this issue: you can set your domain TTL (time-to-live)
low, but no matter how low you set it, there will be a period of time after
an IP address change where some DNS servers will point to your old IP address.
This is an availability risk you have to consider when setting up a service on
a dynamic IP address.</p>
<h2 id="future-steps">
  <a class="heading-anchor" href="#future-steps">Future steps<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>At one point I took a look a the assets of the Hugo theme that I use and noticed
that it includes a dependency named <code>prism.js</code>, which might be a good thing to
include if you want to display code snippets with syntax highlighting. My issue
with it was that it was included on every page load and took up a significant
chunk of transferred data. I decided to remove it, and just like that, the page
loads even faster.</p>
<p>There&rsquo;s still room for improvement. The page currently also includes some custom
fonts. If I decide that a built-in font is good enough, then there&rsquo;s potential
for an additional 0.3 MB of savings.</p>
<p>The web is bloated enough already, but at least I can control what I send to the
client machines on my website.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you don&rsquo;t want to go through all the hassle and just want a website up and
running, just get yourself a cheap virtual machine at a cloud provider, or use
something like Github Pages. Those solutions are less likely to hit limits with
bandwidth.</p>
<p>If you like tinkering and the decentralized, self-hosted web to exist
(<em>not Web 3.0!</em>), then feel free to use this post as inspiration for your very
own website. There&rsquo;s a lot that you can do with limited resources, and it&rsquo;s
fun to push the limit.</p>
<p>And as a quick tech tip: you can use <a href="https://web.archive.org/web/20220110074515/https://ounapuu.ee/posts/2022/01/09/why-i-went-back-to-using-a-thinkpad-from-2012/">The Wayback Machine</a>
as an insurance policy for your website. If you are concerned about it going
down, have them take a snapshot of it and link it somewhere in a comment.</p>
]]></content:encoded></item><item><title>ASRock DeskMini X300: the future form factor of desktop PC-s?</title><link>https://ounapuu.ee/posts/2022/01/17/asrock-x300-future-of-desktops/</link><pubDate>Mon, 17 Jan 2022 07:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/01/17/asrock-x300-future-of-desktops/</guid><description>Honey, I shrunk my desktop PC!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="ASRock DeskMini X300: the future form factor of desktop PC-s?" /><p>I wasn&rsquo;t happy with my <a href="/posts/2021/12/29/vr-vfio-latency/">&ldquo;one machine that does it all&rdquo;</a>
setup, which is why I finally bit the bullet and got myself an <a href="https://www.asrock.com/nettop/AMD/DeskMini%20X300%20Series/index.asp">ASRock DeskMini X300 bare-bones kit</a>.
This is a fantastic little desktop PC kit that is very small, quiet and can
still be configured to have ridiculous amounts of power. In the past. I once
built a low-power server based off of the predecessor, <a href="https://www.asrock.com/nettop/AMD/DeskMini%20A300%20Series/index.asp">the DeskMini A300</a>,
and instantly fell in love with this form factor. Since then, I&rsquo;ve tried to come
up with a reason to get one, and finally I&rsquo;ve got one.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/0-assembled.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/0-assembled_hu_582636fe3dc6562.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The ASRock DeskMini X300, up and running.">

  </a>
  <figcaption class="center">The ASRock DeskMini X300, up and running.</figcaption>
</figure>

<h2 id="configuration">
  <a class="heading-anchor" href="#configuration">Configuration<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Because this is a bare-bones kit, you have to supply your own parts.</p>
<p>My configuration:</p>
<ul>
<li>CPU: AMD Ryzen 7 5700G, locked to 35 W TDP in UEFI settings.</li>
<li>Cooling: Noctua NH-L9a</li>
<li>RAM: 2x 16 GB DDR4-3200 SODIMM</li>
<li>NVMe storage: 2x Samsung SSD 980 500GB</li>
<li>SATA storage: 2x Samsung SSD 870 QVO 4TB</li>
<li>USB storage: 1x Samsung SSD 860 EVO 250GB in an IcyBox USB enclosure</li>
</ul>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/1-mobo.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/1-mobo_hu_dd2b8d53a1ea5414.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Initial test configuration with Ryzen 5 PRO 4650G and 16GB of RAM.">

  </a>
  <figcaption class="center">Initial test configuration with Ryzen 5 PRO 4650G and 16GB of RAM.</figcaption>
</figure>

<p>The use case for my kit is simple: it&rsquo;s my server that hosts all my services and
data, including this blog you&rsquo;re reading.</p>
<p>Why this setup in particular?</p>
<ul>
<li>Most of my storage needs can be served by two 4 TB SSD-s.</li>
<li>8 cores with SMT are perfect for multithreaded workloads, such as <a href="https://jellyfin.org/">Jellyfin</a>
transcoding. This also works well for just running a bunch of services on the same
machine.</li>
<li>Can support up to 64 GB of RAM, which should be plenty in the foreseeable
future.</li>
<li>Supports fast NVMe SSD-s, which are perfect for more IO-sensitive workloads,
such as databases.</li>
<li>Low power usage. Even with my almost maxed out kit, it still uses around
14 W in idle. At most this PC can use around 50-60 watts due to the CPU TDP
limit and SSD-s hitting full load.</li>
</ul>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/3-testbed.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/3-testbed_hu_ccae4dc7a42f9185.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Never assemble the whole PC without checking if it actually works.">

  </a>
  <figcaption class="center">Never assemble the whole PC without checking if it actually works.</figcaption>
</figure>

<h2 id="why-is-this-form-factor-so-good">
  <a class="heading-anchor" href="#why-is-this-form-factor-so-good">Why is this form factor so good?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Desktop PC-s are big. Really big. While the small form factor PC movement has become
more popular lately, the most commonly available cases and parts still end up
taking a lot of space and resources. There are legitimate use cases for these
types of setups, especially if you&rsquo;re running video renders, scientific
simulations or a lot of VM-s as part of a lab. Not every workload needs such a
big setup, however.</p>
<p>The DeskMini X300 looks like a miniature version of a desktop PC in a tower case.
Similar shape and features, but at a fraction of the size and raw resources usage.
One might say that it even looks adorable, similar to how
<a href="https://www.reddit.com/r/pcmasterrace/comments/nlddyc/since_gpus_are_in_short_supply_i_decided_to_build/">Raspberry Pi-based builds look compared to desktops</a>.</p>
<p>This PC takes up just 1.92 liters in volume (excluding the power adapter). For
comparison, a micro-ATX case like <a href="https://www.fractal-design.com/products/cases/meshify/meshify-c-mini-dark-tempered-glass/black/">the Fractal Meshify Mini C</a>,
takes up a whopping 33.4 liters. I don&rsquo;t have the raw numbers regarding material
usage or the weight difference, but this comparison should give you an idea of
the material usage difference between the two.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/5-size.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/5-size_hu_ff89a889b8dda0ca.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Included driver CD for scale. Not sure where you&#39;d insert it, though.">

  </a>
  <figcaption class="center">Included driver CD for scale. Not sure where you&#39;d insert it, though.</figcaption>
</figure>

<h2 id="caveats">
  <a class="heading-anchor" href="#caveats">Caveats<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I love this piece of kit, but I do have to acknowledge that there are some
trade-offs that you should be aware of.</p>
<p>Starting with the obvious one first: you&rsquo;re trading off some expandability.
No discrete GPU-s will fit in this thing, not even an external one due to lack
of Thunderbolt. On the other hand, if you don&rsquo;t foresee a need for such
additions to your PC, then the DeskMini will be a great choice.</p>
<p>Something that&rsquo;s specific to the X300 is the lack of USB connectivity. You get
two USB 3.0 Type-A ports, one USB 2.0 port and a USB 3.2 Gen 1 Type-C port as
well. If you have a USB hub, then this won&rsquo;t be much of an issue, but this
configuration is quite limited compared to most modern desktop motherboards.</p>
<p>The motherboard inside this thing can also be a point of concern. It&rsquo;s a
non-standard form factor, meaning that in case of failure you&rsquo;re unlikely to
easily find a replacement. The most obvious step here would be to either repair
it or get another DeskMini kit to replace your existing one.</p>
<p>One aspect of the DeskMini X300 that you may care about is the fact that the
power supply is an external 19V 120W power brick. This does mean that replacing
the power supply won&rsquo;t be much of an issue, but you do have to take this into
account when planning your build. The power brick is quite big and has to be
placed somewhere, after all. In my setup, I&rsquo;ve opted for sticking it to the
underside of my desk with double-sided tape.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/8-powersupply.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/8-powersupply_hu_3786ce24a6498256.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="How to hide bulky power supplies: the tutorial.">

  </a>
  <figcaption class="center">How to hide bulky power supplies: the tutorial.</figcaption>
</figure>

<h2 id="gpu-s-apu-s-and-the-future">
  <a class="heading-anchor" href="#gpu-s-apu-s-and-the-future">GPU-s, APU-s, and the future<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>For anyone who&rsquo;s followed the GPU market in 2021/2022, the ridiculously high pricing
of GPU-s shouldn&rsquo;t come as a surprise. As a firm believer in thinking that low
power computing is the future, I think that this presents a great opportunity
to start thinking differently about our computing architecture.</p>
<p>AMD introduced the concept of <a href="https://en.wikipedia.org/wiki/AMD_Accelerated_Processing_Unit">APU-s back in 2011</a>.
In its current iteration in the form of AMD Ryzen 5000 series APU-s, they provide
a compelling package, combining powerful CPU cores with a decent GPU that&rsquo;s perfectly
capable of many tasks, including low-spec gaming.</p>
<p>I&rsquo;ve <a href="/posts/2021/11/03/tech-rants-1/">previously covered what I think about the state of computer hardware and the resource
usage associated with it</a>. It&rsquo;s possible that
we&rsquo;re simply in a time in history where resource abundance allows us to push the
limit of what computer hardware is capable of without thinking much about the
cost. At some point we do need to address that issue, and I think APU-s will
play a role in it.</p>
<p>We already have examples of what APU-like chips can be capable of in the form of
the last two console generations. To get an idea about the power usage numbers,
check out the <a href="https://www.playstation.com/en-gb/legal/ecodesign/">power usage statistics shared by Sony for the PS4 and PS5</a>.
The power usage of the PS5 is still almost 200 W under load, which isn&rsquo;t that great,
but that&rsquo;s likely due to the high performance goals set for the console itself.
You&rsquo;d have to give up some image quality or performance for a more efficient setup,
which is something the marketing department isn&rsquo;t probably very happy about, given
that they&rsquo;re in direct competition with Microsoft with their newest XBOX lineup
that is also pushing the limits of the custom APU inside it.</p>
<p>The integrated GPU solutions that AMD and Intel have put out are becoming more
and more capable. Even an AMD Ryzen 3 2200G from 2018 with its measly 4 cores
and a Vega 8 GPU is still capable enough to run GTA V at 1080p with low-medium
settings smoothly (60 FPS or more). You do have to make a conscious trade-off
in image quality and performance when relying on APU-s, but if you&rsquo;re willing
to make that trade-off, you can get a decent gaming experience.</p>
<p><a href="https://store.steampowered.com/steamdeck/">Even the Steam Deck is shipping with a custom AMD APU.</a>
What makes this one different from AMD-s previous APU-s is the inclusion of a
modern GPU core based on the RDNA 2 architecture, which should be a big jump
from the relatively old Vega-based GPU-s that desktop APU-s have shipped with.</p>
<p>If it weren&rsquo;t for the progress in gaming tech, such as high refresh rate monitors
and ever-increasing system requirements for newer games, APU-s would be a good
default choice for casual gamers, negating the need to get a huge box that you
have to somehow also fit on your desk.</p>
<p>I have run on an APU-based setup and was happy with the experience, unfortunately
an APU-based machine just doesn&rsquo;t cut it for virtual reality workloads, yet.</p>
<h2 id="comparison-to-tinyminimicro-pc-s">
  <a class="heading-anchor" href="#comparison-to-tinyminimicro-pc-s">Comparison to TinyMiniMicro PC-s<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p><a href="https://www.servethehome.com/introducing-project-tinyminimicro-home-lab-revolution/">ServeTheHome&rsquo;s TinyMiniMicro series</a>
gives a good overview of the options available for someone who wants a very small
1 liter PC to do all their work on. Since these machines are also very small,
power-efficient and yet still quite powerful, I think a comparison between the
two is a reasonable one.</p>
<p>One area where the TinyMiniMicro PC-s win is an obvious one: the size. They are
about half the size of the DeskMini X300: 1 liter vs 1.92 liters.</p>
<p>TinyMiniMicro PC-s are also abundant on the used market with various configurations.
In most cases, the storage and RAM are upgradeable, and with some older models
you&rsquo;ll find that the CPU is also socketed. Depending on your market, this means
that you may be able to get a whole PC for cheaper than the DeskMini + the rest
of the components (CPU, RAM, storage, Wi-Fi etc.).</p>
<p>The size and cost benefits do come with some compromises that are not acceptable
for my use case. At 1 liter, the only option you have is to include a blower
type cooler in your PC. This type of cooler is similar to the ones found in
laptops and has in my experience resulted in a lot of annoying noise under heavy
load.</p>
<p>The UEFI settings on these machines may also be quite limited. Sure, if you just
need the basics, these will be fine, but if you want to configure the fan
behaviour, you might find yourself unable to do so. On the DeskMini, you can
setup the CPU fan to run just the way you like it. In my case, the fan only
turns on when the system is under load, the fan is completely stopped while the
machine is idle.</p>
<p>The DeskMini also allows you to change out the CPU cooler with anything that&rsquo;s
AM4 socket compatible. The case of course sets some limits to that,
<a href="https://www.reddit.com/r/Amd/comments/enw3up/a3003400g_w_ml120_aio_mod/">unless you&rsquo;re a madlad who doesn&rsquo;t let boundaries bother them.</a>
With the <a href="https://noctua.at/en/nh-l9a-am4">Noctua NH-L9a AM4</a>, the setup is very
quiet, especially once you limit the CPU TDP and adjust the fan curve. In my
experience, the &ldquo;coil whine&rdquo; noise that the system produces under load is more
audible than the CPU fan itself.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/2-cooler-installed.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/2-cooler-installed_hu_1ab963d658dec229.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Low profile Noctua cooler: looks good, is quiet and keeps the system cool.">

  </a>
  <figcaption class="center">Low profile Noctua cooler: looks good, is quiet and keeps the system cool.</figcaption>
</figure>

<p>When it comes to storage options, the DeskMini is an obvious winner. In modern
TinyMiniMicro machines that I&rsquo;ve seen, you can at most install two NVMe SSD-s.
This is a step up from older machines and you can still do a lot with that, but
the DeskMini trumps that with the addition of two SATA ports, which allows you
to go crazy with the storage configuration.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/4-bulk-storage.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/4-bulk-storage_hu_3f5d94339265be4d.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="8TB of solid state storage. Bonkers.">

  </a>
  <figcaption class="center">8TB of solid state storage. Bonkers.</figcaption>
</figure>

<p>Both the DeskMini and TinyMiniMicro-series PC-s are fantastic, but for my use
case the DeskMini X300 was the obvious choice.</p>
<h2 id="tech-tip-vesa-mounts-for-what">
  <a class="heading-anchor" href="#tech-tip-vesa-mounts-for-what">Tech tip: VESA mounts, for what?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The DeskMini X300 is so light and small that you can easily attach it to a
monitor arm using a piece of foam and long velcro strips.</p>









<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/6-custommount.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/6-custommount_hu_2101070382b2a45.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="DeskMini X300 mounted on a monitor arm.">

  </a>
  <figcaption class="center">DeskMini X300 mounted on a monitor arm.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2022/01/17/asrock-x300-future-of-desktops/media/7-custommount.jpg">
    <img src="/posts/2022/01/17/asrock-x300-future-of-desktops/media/7-custommount_hu_f7b4950e8939cd42.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Behind the scenes.">

  </a>
  <figcaption class="center">Behind the scenes.</figcaption>
</figure>

<h2 id="future-plans">
  <a class="heading-anchor" href="#future-plans">Future plans<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;m hoping that the current DeskMini-based server configuration is the one that
will last me a while. The obvious upgrades in the future would be to max out the
RAM at 64 GB and upgrade the NVMe and SATA storage to whatever options are
available in the future. I&rsquo;m not expecting the DeskMini X300 to get a CPU
upgrade, which isn&rsquo;t too tragic, given that the Ryzen 7 5700G has 8 fast cores.</p>
<p>My adventures in low power computing may take me to another setup in the future.
Until then, I&rsquo;ll see how the DeskMini does. So far, it has met my expectations
in performance, power usage, reliability and noise.</p>
<h2 id="future-of-desktop-computing">
  <a class="heading-anchor" href="#future-of-desktop-computing">Future of desktop computing?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Predictions are difficult to make, especially in turbulent times that we&rsquo;ve
found ourselves in. I do hope that this form factor takes off and that we
reevaluate our current computing workloads to be more suitable for machines
that use a lot less power.</p>
<p>Constraints often result in clever tricks and fantastic end results. Hopefully
we&rsquo;ll see something similar in the future.</p>
<p>To get an idea of what you can achieve with very limited hardware, check out
the <a href="https://www.youtube.com/c/CodingSecrets">Coding Secrets YouTube channel</a>
that showcases all the tricks and thinking behind some of the most impressive
effects on game consoles from early 90&rsquo;s.</p>
<p>Sure, you can argue that not having to think about such limitations can help
create solutions faster and that definitely has some value, but at some point
we need to start optimizing. Computing resources are cheap right up to the point
where every app on your PC thinks the same way.</p>
]]></content:encoded></item><item><title>VR, VFIO and how latency ruined everything</title><link>https://ounapuu.ee/posts/2021/12/29/vr-vfio-latency/</link><pubDate>Wed, 29 Dec 2021 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/12/29/vr-vfio-latency/</guid><description>Alternative title: "Honey, I completely changed my server setup again!"</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="VR, VFIO and how latency ruined everything" /><p>I&rsquo;ve been running my <a href="/posts/2021/08/29/testing-gpu-passthrough-on-amd-ryzen-5700g/"><em>all-in-one</em></a>
PC for a while now. It was my desktop, my NAS and my gaming PC.
However, during the next couple of months I kept hitting small bumps along the
road. Most of these were quite straightforward to fix, but there is one that
finally convinced me to go back to a simpler setup.</p>
<h2 id="iscsi">
  <a class="heading-anchor" href="#iscsi">iSCSI<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>As mentioned in <a href="/posts/2021/10/13/diy-cloud-gaming-nvidia-moonlight/">one of my previous posts</a>,
I had set up the storage on my gaming VM over iSCSI. If you don&rsquo;t know what
iSCSI is: think of it like a hard drive that you can hook up to your machine
over the network. This setup had a couple of benefits: the amount allocated to
the VM was flexible and I would always have a snapshot of my game data in case
the Windows VM decided to nuke itself.</p>
<p>What I didn&rsquo;t take into account was the configuration. <code>tgt</code> allows you to
define the IP address of the client machine, which can be seen as an additional
layer of security. My gaming VM has two virtual NIC-s, one pointing to the
actual physical network, and another one to a virtual one. This resulted in the
iSCSI connection being flaky on startup: the disk was not present in the VM on
first boot, but was there after a reboot.</p>
<p>This issue was gone once I removed this restriction from the iSCSI target
configuration on the Linux VM. My best guess is that the iSCSI stack in Windows
might have tried to initiate a connection over the wrong NIC, depending on
whichever one was brought up first.</p>
<p>After &ldquo;solving&rdquo; this issue, it had been smooth sailing.</p>
<h2 id="gpu-audio-issues">
  <a class="heading-anchor" href="#gpu-audio-issues">GPU audio issues<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>When the Windows VM had been on for a while, the HDMI audio output would start
to glitch out after a while, with the audio sounding slow, robotic and garbled.
After doing some research, I found some resources that mentioned enabling MSI
interrupts in Windows. The guide for this can be found over at
<a href="https://forums.guru3d.com/threads/windows-line-based-vs-message-signaled-based-interrupts-msi-tool.378044/">Guru3D forums</a>.</p>
<p>After tweaking the Windows registry settings and reminding myself that I do have
snapshots to fall back to in case I mess up, I got the issue fixed.</p>
<h2 id="gpu-driver-issues">
  <a class="heading-anchor" href="#gpu-driver-issues">GPU driver issues<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Whenever there&rsquo;s a new big and popular game released, NVIDIA usually releases
an updated version of their GPU drivers. I try to keep my software up to date,
so I usually install these updates when they come out. Just one problem: when I
upgrade the GPU drivers in the VM, the screen will stay black. After some time
passes, I have to force a reboot using <code>virt-manager</code>.</p>
<p>I have not looked into this issue yet as it only happens during driver updates,
but it&rsquo;s definitely an annoying thing to have.</p>
<h2 id="uefi-and-csm">
  <a class="heading-anchor" href="#uefi-and-csm">UEFI and CSM<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>UEFI updates have a bad habit of resetting all the custom settings that you
have made, and at least with the motherboards I have used, the settings cannot
be restored if the backed up settings are from an older UEFI version. This
means that I have to navigate the UEFI quite often to configure all the
settings that I need to have in place for VFIO to work.</p>
<p>There is one setting that I didn&rsquo;t expect to cause that much trouble though:
CSM support. CSM (compatibity support module) is generally enabled by default
and allows you to boot off of legacy operating systems if needed. I don&rsquo;t have
that requirement, so I went ahead and set my boot options to boot in UEFI mode
only.</p>
<p>Reboot, start up Fedora, and boom, anything VFIO related is spewing errors like
crazy.</p>
<p>Turns out that enabling UEFI only mode in UEFI settings somehow grabs the GPU
and causes problems when you try to then pass the GPU to a VM. While in this
mode, I noticed that the GPU was also shown in a separate menu in UEFI settings.
Enabling CSM support fixed this issue for me.</p>
<h2 id="vr-and-usb-issues">
  <a class="heading-anchor" href="#vr-and-usb-issues">VR and USB issues<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With the situation in the world being less than optimal, I decided to spice up
my gaming setup with the addition of a <a href="https://www.vive.com/us/product/vive-cosmos/features/">HTC Vive Cosmos</a>
in case in-door activities become much more popular suddenly.</p>
<p>First issue: I can&rsquo;t get the damn thing working. My gaming VM setup has the
<a href="https://www.inateck.com/products/inateck-kt4006-dual-port-usb-3-0-pci-express-card-20-pin-connector-no-power-connection">inateck KT4006</a>
passed through so that I can plug peripherals to the PC and make them available
to the gaming VM with ease. After plugging everything in according to
instructions and turning the link box on, I&rsquo;m met with a barrage of USB
connected-disconnected sound effects. 6 or 7 cycles later the sound stops, and
with that do the rest of my USB devices.</p>
<p>I took the USB 3.0 card and tried it in an older machine that doesn&rsquo;t have a
fancy VFIO setup on it. Same issue. However, when connected to an USB 2.0 port,
the setup shows a warning in VIVE Console, but at least it works! Since my PC
literally has no USB 2.0 ports, I had to get a bit creative and plug an USB 2.0
extension cable between the PC and the USB 3.0 cable coming from the link box.</p>
<p>With the help of my friend I got confirmation that the issue is indeed with my
USB ports. I also ordered a different USB PCIe card from inateck, this time the
<a href="https://www.inateck.com/products/pci-e-to-usb-3-0-4-ports-pci-express-card-and-15-pin-power-connector-red-kt4001">inateck KTU3FR-4P</a>.
I made the assumption that since <a href="https://www.vive.com/eu/support/vive/category_howto/headset-not-detected-due-to-usb-issue.html">the VIVE support page also recommends an inateck card</a>,
then they must be fit for purpose.</p>
<p>Nope. The second card apparently has the same chipset and the same issue.</p>
<p>What did end up working was a random VIA USB 3.0 PCIe card, which shows up as
<code>VIA Technologies, Inc. VL805/806 xHCI USB 3.0 Controller</code> on my machine. Just
one issue: it has PCIe device reset issues. If I shut down the Windows VM and
start it up again, I would sometimes get a bunch of <code>IO_PAGE_FAULT</code> errors in
my kernel logs. No worries, guess I&rsquo;ll just avoid rebooting a notoriously
reboot-happy OS.</p>
<h2 id="latency-the-straw-that-broke-the-camels-back">
  <a class="heading-anchor" href="#latency-the-straw-that-broke-the-camels-back">Latency: the straw that broke the camel&rsquo;s back<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If there&rsquo;s one thing you don&rsquo;t want to see in a VR gaming setup, it&rsquo;s latency.</p>
<p>I&rsquo;ve covered <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/">the tweaks I&rsquo;ve made to my setup in a previous post</a>.
Turns out that those might not be enough. The <a href="https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Example_with_systemd">CPU isolation using systemd</a>
works well in general, but not with kernel threads.</p>
<p>Whenever I did something IO heavy on an NVMe-based btrfs file system, it would
introduce stutter to the gaming VM. Running a scrub operation on the filesystem
was enough to put a huge load on the CPU, likely due to the raw speed that the
NVMe SSD-s can provide. This results in the gaming VM experiencing stutter
that ruins the whole experience.</p>
<p>Here&rsquo;s an illustration.</p>









<figure class="center">
  <a href="/posts/2021/12/29/vr-vfio-latency/media/normalusage.jpg">
    <img src="/posts/2021/12/29/vr-vfio-latency/media/normalusage_hu_bddd6f0b9c862f0f.webp"
     width="956"
     height="800"
     loading="lazy"
     decoding="async"
     alt="SteamVR performance statistics with a light load on the host system.">

  </a>
  <figcaption class="center">SteamVR performance statistics with a light load on the host system.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/12/29/vr-vfio-latency/media/latencyhell.jpg">
    <img src="/posts/2021/12/29/vr-vfio-latency/media/latencyhell_hu_6ffdf367424bccee.webp"
     width="927"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The purple spikes mean that you are having a real bad time right now.">

  </a>
  <figcaption class="center">The purple spikes mean that you are having a real bad time right now.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/12/29/vr-vfio-latency/media/latencynative.jpg">
    <img src="/posts/2021/12/29/vr-vfio-latency/media/latencynative_hu_d9c371c91ecc08fe.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="For comparison: VR performance running natively on Windows 10.">

  </a>
  <figcaption class="center">For comparison: VR performance running natively on Windows 10.</figcaption>
</figure>

<p>Similar issues could be observed whenever I tried to run another VM that
shares the same cores.</p>
<p>I looked into alternative solutions as well, and it does seem to be possible
to also isolate those CPU cores from the kernel. They will probably work to
some extent, but implementing them feels a bit hacky at the moment. I&rsquo;m hoping
that in the future these kinds of tweaks will be exposed as a simple checkbox
in <code>virt-manager</code> itself.</p>
<p>At that point I had enough. If I&rsquo;m not going to be able to use the machine for
other purposes at the same time without experiencing all these issues and
having to work around them, then I&rsquo;ll just go back to a simpler setup. I&rsquo;ll lose
some of the benefits, but at least I don&rsquo;t have to spend time debugging all
these issues.</p>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>VFIO and virtualization are still interesting topics to learn about and try
out, but for my use case they are just too limiting. I&rsquo;d imagine that an use
case that didn&rsquo;t have such strict latency requirements would still be able to
run just fine, unfortunately gaming just isn&rsquo;t one of them.</p>
<p>This experience has been quite fun in general, but I&rsquo;m calling quits, at least
for now. The one machine that does it all turned out to be a jack of all
trades, master of none.</p>
]]></content:encoded></item><item><title>Self-hosting Wikipedia using Kiwix</title><link>https://ounapuu.ee/posts/2021/12/09/self-hosting-wikipedia/</link><pubDate>Thu, 09 Dec 2021 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/12/09/self-hosting-wikipedia/</guid><description>Hosting your own Wikipedia instance has never been this easy!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Self-hosting Wikipedia using Kiwix" /><p>Do you have a need to host Wikipedia on your computer?</p>
<p>Or a StackExchange site, like <a href="https://superuser.com/">Super User</a>?</p>
<p>It&rsquo;s easier than you think!</p>









<figure class="center">
  <a href="/posts/2021/12/09/self-hosting-wikipedia/media/image.jpg" aria-label="View full-size image">
    <img src="/posts/2021/12/09/self-hosting-wikipedia/media/image_hu_735508aea9ceb050.webp"
     width="920"
     height="518"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<h2 id="step-1-download-stuff">
  <a class="heading-anchor" href="#step-1-download-stuff">Step 1: download stuff!<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The <a href="https://www.kiwix.org/en/">Kiwix project</a> provides ZIM files for many popular websites, including Wikipedia.
These files can be downloaded <a href="https://wiki.kiwix.org/wiki/Content_in_all_languages">over at Kiwix wiki.</a></p>
<p>Take a look at the content packages available and download those that you are interested in.</p>
<h2 id="step-2-install-kiwix">
  <a class="heading-anchor" href="#step-2-install-kiwix">Step 2: install Kiwix<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Kiwix provides <a href="https://www.kiwix.org/en/download/">all sorts of clients for different operating systems</a>. If you don&rsquo;t
want to go crazy with setting up a server and you just want to browser your offline copy of Wikipedia or any other
resource, then go ahead and use that.</p>
<p>However, if you want to make the resources available for other people as well, then you need to install <code>kiwix-serve</code>.
On Debian and Ubuntu systems, this is just a <code>sudo apt install kiwix-tools</code> in your terminal.</p>
<p>Once you have it installed, all you have to do is to run <code>kiwix-serve -p 8080 your-file-here.zim</code> and your content
package is served to anyone who can connect to your machine with a browser over port 8080.</p>
<p>If you have multiple ZIM files in the same folder, then you can serve all of them at once with something like
<code>kiwix-serve -p 8080 *.zim</code>.</p>
<h2 id="step-3-enjoy">
  <a class="heading-anchor" href="#step-3-enjoy">Step 3: enjoy!<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>You should now be up and running with your very own hosted Wikipedia instance!
Just keep in mind that your copy might not be 100% up to date. The Kiwix project does repackage these sites quite
regularly so keep an eye out for updates.</p>
<h2 id="tips-and-tricks">
  <a class="heading-anchor" href="#tips-and-tricks">Tips and tricks<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have set up my own Kiwix instance and the way it works is quite simple.</p>
<p>I use <a href="https://deluge-torrent.org/">Deluge</a> to download and seed the content packs that I have downloaded.</p>
<p>Then I have also set up a <code>systemd</code> service that automatically starts Kiwix on boot. It is located at
<code>/etc/systemd/system/kiwix-serve.service</code> and looks like this:</p>
<pre tabindex="0"><code>[Unit]
Description=Serve all the ZIM files loaded on this server

[Service]
Restart=always
RestartSec=15
User=kiwix
ExecStart=/usr/bin/bash -c &#34;/usr/bin/kiwix-serve -p 8080 /path/to/your/files/*.zim&#34;

[Install]
WantedBy=network-online.target
</code></pre><p>Note that I have set up a separate non-interactive user for this purpose. The path to the ZIM files simply refers to
the download folder of the Deluge torrent client.</p>
<p>Making this available to the world is simply a matter of either exposing the selected port to the world, or using <code>nginx</code>
as a reverse proxy. There are plenty of guides available on how to achieve the latter so I won&rsquo;t go into detail about
that here.</p>
<p>That&rsquo;s it!</p>
<h2 id="2024-09-05-update">
  <a class="heading-anchor" href="#2024-09-05-update">2024-09-05 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s been a fun experiment, but LLM-bots are overwhelming my Kiwix instance and I can&rsquo;t be bothered with setting up
any protections right now, so the <code>kiwix.ounapuu.ee</code> instance is shut down for now.</p>
]]></content:encoded></item><item><title>DIY cloud gaming: NVIDIA and Moonlight</title><link>https://ounapuu.ee/posts/2021/10/13/diy-cloud-gaming-nvidia-moonlight/</link><pubDate>Wed, 13 Oct 2021 05:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/10/13/diy-cloud-gaming-nvidia-moonlight/</guid><description>Comparing the experience that AMD and NVIDIA can provide in a DIY cloud gaming setup.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="DIY cloud gaming: NVIDIA and Moonlight" /><p>As you might have read from <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/">my previous post on this topic</a>, I
have a pretty neat &ldquo;cloud&rdquo; gaming setup running. I have one powerful desktop PC, one virtual machine with a GPU attached
to it, and client machines that can be used to stream games from. To keep things simple (and because my current ISP is
unbelievably bad), I have so far used streaming only over my local network.</p>
<p>However, there were some pretty annoying issues with this setup:</p>
<ul>
<li>The AMD GPU encoder is bad. 720p streaming was the best I could do if I wanted reasonable performance.</li>
<li>The Windows 10 VM would sometimes not be able to start the host encoder, and the GPU drivers reported issues. This was
fixed with a couple of reboots to the VM and I suspect that this may be related to the notorious GPU reset issues that
AMD cards are infamous for in the VFIO world, but I wasn&rsquo;t interested in digging that deep into that topic.</li>
<li>The stream would sometimes randomly crash or lag. This might have been down to the AMD GPU
or <a href="https://parsec.app/">Parsec</a> itself.</li>
</ul>
<p>I read about this topic for a while and found that the overwhelming number of threads related to this topic recommend an
NVIDIA GPU and Moonlight for the best streaming experience. And so I went out to get one.</p>
<h2 id="the-gpu">
  <a class="heading-anchor" href="#the-gpu">The GPU<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s 2021. The world is on fire and GPU prices are insane. With that in mind, I tempered my expectations and went for
something simple: a NVIDIA GTX 1060 6G by MSI. Simple, relatively modern for my games and the price was around the
retail price 5 years ago (260 EUR), which is the best you can do in these lousy times.</p>
<p>But hey, it works! From the testing I
did <a href="/posts/2021/08/29/testing-gpu-passthrough-on-amd-ryzen-5700g/">in a previous post</a>, I knew that NVIDIA had finally
stopped intentionally throwing <code>error code 43</code> in their drivers, which made this option viable. Replacing the GPU was
simple, I just had to change the PCI device ID-s according to the VFIO setup guide and changed the devices attached to
the Windows 10 VM using <code>virt-manager</code>, and that was it!</p>
<h2 id="parsec-amd-vs-nvidia">
  <a class="heading-anchor" href="#parsec-amd-vs-nvidia">Parsec: AMD vs NVIDIA<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Since I was already using Parsec for my streaming purposes, I decided to do a quick test to see what the difference is
between the two cards.</p>
<p>The previous GPU was an AMD Radeon RX 570 4GB by Sapphire. These two GPU-s are in the same performance class, which
makes for a good comparison.</p>
<p>Here are some results taken in two quick testing sessions in Dirt Rally. Take these results with a spoonful of salt as
these have not been conducted with any kind of standards. I just picked the same graphics preset, resolution and let it
run with Parsec statistics view open.</p>
<h3 id="h264">
  <a class="heading-anchor" href="#h264">H.264<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>AMD RX 570: 10ms</p>
<p>NVIDIA GTX 1060: 3ms</p>
<h3 id="h265">
  <a class="heading-anchor" href="#h265">H.265<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>AMD RX 570: 8ms</p>
<p>NVIDIA GTX 1060: 3ms</p>
<p>The difference in the encode performance is huge, especially if you consider that the time between two frames is 16.6ms
for a 60 FPS stream. Some of that budget is also taken up by network and decode latency in the client, so the shorter
the encode time is, the better.</p>
<p>Parsec is fine, but I have had some trouble getting GPU-accelerated decode working on my Linux clients, and it also
lacks an iOS client. While the latter isn&rsquo;t a deal-breaker, the first one definitely is.</p>
<h2 id="moonlight-an-open-source-gem">
  <a class="heading-anchor" href="#moonlight-an-open-source-gem">Moonlight: an open-source gem<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p><a href="https://moonlight-stream.org/">Moonlight</a> is an alternative to Parsec. It implements the NVIDIA GameStream protocol and
has clients for most common platforms. My testing has been performed on Linux clients running Fedora 34, a Windows 10
laptop (ThinkPad X230), iPhone SE 2020 and an old Google Nexus 5. I also made an attempt to run the Moonlight client on
a Raspberry Pi 1 B+, but it seems that it is simply too old for the Moonlight client, resulting in an error on startup.</p>









<figure class="center">
  <a href="/posts/2021/10/13/diy-cloud-gaming-nvidia-moonlight/media/image.jpg">
    <img src="/posts/2021/10/13/diy-cloud-gaming-nvidia-moonlight/media/image_hu_10280f4a7e25eb3d.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="GTA V on a Google Nexus 5? More likely than you think.">

  </a>
  <figcaption class="center">GTA V on a Google Nexus 5? More likely than you think.</figcaption>
</figure>

<p>To set up Moonlight, I opened up the client and tried the automatic detection over the network. Unfortunately that did
not yield any results, so I input the IP address of the Windows VM manually. That worked well. This initiated a pairing
process that I had to continue using Parsec, because you need to input a code on the host machine. After that, I had to
quit Parsec and start streaming using Moonlight.</p>
<p>OK, not quite yet. Moonlight is able to detect the games installed on your system, but for a remote desktop experience,
you
<a href="https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide#using-moonlight-to-stream-your-entire-desktop">have to do a small tweak</a>
for it to be equivalent to the experience you get from Parsec.</p>
<p>One thing that I noticed at the start was that the image quality on the desktop isn&rsquo;t as good as on Parsec. However, it
more than makes up for it in-game. Moonlight just works. There are plenty of knobs you can turn as well, including
configuring the image quality by setting the resolution, framerate and network limits.</p>
<p>What makes Moonlight more suitable for me is that
the <a href="https://flathub.org/apps/details/com.moonlight_stream.Moonlight">Linux client packaged as a Flatpak</a>
is able to use the GPU for hardware-accelerated decode. The experience is great on a Linux machine and it just works,
which is not something you can always expect to happen. Even an older XBOX ONE controller connected over Bluetooth works
just fine over Moonlight!</p>
<p>The only issues that I had with Moonlight were later determined to be caused by networking issues. This shows up well on
the integrated statistics that Moonlight provides using the <code>Ctrl + Alt + Shift + S</code> key combination under
the <code>Network jitter</code> field. After stopping some services on my network, the issues went away.</p>
<h2 id="the-setup-one-month-later">
  <a class="heading-anchor" href="#the-setup-one-month-later">The setup: one month later<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>After a month of use, I have made some adjustments to the setup. I used to keep the VM running so that I could just jump
in and start playing whenever I liked it, but due to a tweak I made in the name of improving gaming performance, half
the CPU cores on my system were not available for other purposes, such as suffering through IntelliJ indexing the
project again. I decided to only power on the VM if I actually was about to take the time to play it. I haven&rsquo;t yet
figured out the best way to make this more convenient, though. I did make the &ldquo;Calculator&rdquo; key on my keyboard start/stop
the VM on demand, but then GNOME started ignoring the shortcut I had setup and opened the calculator anyway, so that was
a short-lived tweak.</p>
<p>A bigger change that I made to the setup was to store all my games on my ZFS pool that lives in another VM. For that,
I <a href="https://forum.level1techs.com/t/run-your-steam-library-from-a-nas-break-a-leg-challenge-update/107912">setup an iSCSI target using this guide as a starting point</a>
. I used the <a href="https://packages.debian.org/bullseye/tgt">tgt</a> package instead. That has worked out surprisingly well, but
the iSCSI target does not want to properly connect in the Windows VM on the first boot, which is mildly annoying. I soon
discovered that spinning rust just does not cut it and got more SSD-based storage, otherwise other processes on the NAS
could wreak havoc on the gaming experience in games like GTA V. Those issues were manifesting as long loading times and
objects popping in too late, resulting in half the roads and building being missing while driving around the map. The
iSCSI target solution also comes with the added bonus of having a proper backup of all my games. If Windows decides to
blow itself up again and I don&rsquo;t have a backup of the VM ready, then I could just reinstall it and not worry about
downloading and installing all the games again.</p>
<h2 id="verdict">
  <a class="heading-anchor" href="#verdict">Verdict<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Overall, I&rsquo;m very happy about the setup. I don&rsquo;t use it all too often, but occasionally launching <em>art of rally</em> or
<em>BeamNG.drive</em> on any random device I own is great. I do have some concerns about the future of this setup, especially
with Windows 11 having more strict system requirements and newer games demanding more performance. For the time being,
this works and I intend to keep it that way.</p>
<p><em>The one box that does it all</em>: so far so good!</p>
]]></content:encoded></item><item><title>DIY cloud gaming setup with VFIO, Parsec and AMD</title><link>https://ounapuu.ee/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/</link><pubDate>Tue, 07 Sep 2021 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/</guid><description>A build log of how I set up my own 'cloud gaming' setup, including all the issues I faced and attempts to fix those.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="DIY cloud gaming setup with VFIO, Parsec and AMD" /><p>This is a follow-up to <a href="/posts/2021/08/29/testing-gpu-passthrough-on-amd-ryzen-5700g/">my previous post</a> where I covered
the VFIO setup in general. For many people that would have been good enough, but my goal with this setup was to have a
powerful gaming setup that I could access from my living room PC with 20 meters of Ethernet cables between the two.</p>
<h2 id="cloud-gaming">
  <a class="heading-anchor" href="#cloud-gaming">Cloud gaming?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The concept of <a href="https://en.wikipedia.org/wiki/Cloud_gaming">cloud gaming</a> has become more popular lately,
with <a href="https://www.xbox.com/en-US/xbox-game-pass/cloud-gaming">Microsoft</a>,
<a href="https://stadia.google.com/">Google</a>, <a href="https://www.NVIDIA.com/en-eu/geforce-now/">NVIDIA</a> and others offering services
that allow you to stream games to your device. These setups usually include a powerful server in a datacenter rendering
the game and sending the compressed video stream to your device. This works surprisingly well, but due to high cost,
poor internet connectivity in many places in the world
and <a href="https://www.NVIDIA.com/en-us/geforce/forums/gfn-announcements/22/346564/2k-games-on-geforce-now/">licensing issues</a>
, this setup might not work well for everyone.</p>
<p>However, if you already own a moderately powerful gaming PC and would like to use it to play games you already own over
the network, then there are plenty of solutions that can get you there.</p>
<p>Here are some options:</p>
<ul>
<li><a href="https://store.steampowered.com/remoteplay">Steam remote play</a>: works for games launched via Steam.</li>
<li><a href="https://parsec.app/">Parsec</a>: able to stream the whole desktop, including games.</li>
<li><a href="https://moonlight-stream.org/">Moonlight</a>: same, but only usable on hosts with NVIDIA GPU-s due to the implementation
relying on NVIDIA&rsquo;s GameStream protocol.</li>
</ul>
<p>In the past, I&rsquo;ve had OK results with Steam remote play, but the limiting factor has been the reliance on Steam. I have
bought a couple of games from <a href="https://www.gog.com/">GOG</a> as well, which I could probably also play remotely by
launching them via Steam, I just don&rsquo;t want to go through the hassle.</p>
<p>For this setup I&rsquo;ve opted to go with Parsec. It&rsquo;s not perfect, but it&rsquo;s still good enough for our purposes. The GPU
we&rsquo;re using (AMD Radeon RX 570) also limits our options because it won&rsquo;t work with Moonlight.</p>
<p>The installation of Parsec is pretty straightforward: just install it on your host and client machines. In my case the
client machine is
a <a href="/posts/2021/06/28/breaking-and-fixing-thinkpad-x230/">Lenovo ThinkPad X230 that was brought back from the dead</a>
. It&rsquo;s not powerful, but at least it can do H.264 hardware decoding and it uses only 12W of power when idle, making it a
perfect candidate for testing this out. It&rsquo;s also worth mentioning that both machines are connected on the local network
using an Ethernet connection to avoid Wi-Fi becoming a bottleneck.</p>
<h2 id="vfio-gaming-and-you">
  <a class="heading-anchor" href="#vfio-gaming-and-you">VFIO, gaming and you<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>What turned out to be a bigger hurdle was the performance of games inside the VM. After getting everything running with
the VFIO setup, I didn&rsquo;t really spend any time trying to optimize the setup for the smoothest experience. When trying to
actually run this setup, I ran into quite a few problems with performance which mainly manifested as stutters and
unusually low framerates. Turns out that gaming has stricter latency requirements than other server workloads.</p>
<p>Thanks to the <a href="https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Performance_tuning">great guide in Arch Wiki</a>,
I could get a lot of ideas on what to try out to improve the performance of this gaming virtual machine.</p>
<p>Before doing anything, I ran some benchmarks to get a sense of what performance levels I&rsquo;m dealing with. To test out
each individual change, I used GTA V as the gaming benchmark since it was pretty good at pointing out any performance
issues.</p>
<p>Here&rsquo;s a list of things that I ended up doing:</p>
<ul>
<li>setting the CPU model to <code>host-passthrough</code> in <code>virt-manager</code></li>
<li><a href="https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Dynamically_isolating_CPUs">isolating CPU-s dynamically</a>
whenever the VM starts
and <a href="https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#CPU_pinning">pinning those CPU-s</a> to the VM to avoid
the host OS and other VM-s from using those cores</li>
<li>setting the CPU governor to performance on isolated cores to rule out issues with the CPU not clocking high enough and
switching between idle/load power
modes: <code>echo performance &gt; /sys/devices/system/cpu/cpu[4-7]/cpufreq/scaling_governor</code></li>
<li><a href="https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Static_huge_pages">enabling static hugepages</a> to rule out
issues stemming from poor memory access speeds</li>
<li>disabling SMT in UEFI settings to get rid of one additional variable</li>
<li>getting a 64 GB DDR4-3600 memory kit to allocate more RAM to the VM (16 GB) and leave enough for the host machine and
other services</li>
</ul>
<p>The golden rule of troubleshooting is to change one variable at a time and comparing results. Not every change that I
made ended up being a positive one. For example, when configuring the VM to use 4 cores and 8 threads instead of plain 4
cores, I saw the framerates in GTA V drop 50%. I assume that the VM treated the &ldquo;SMT cores&rdquo; as real ones, causing the
Windows scheduler to make incorrect decisions.</p>
<p>After playing around with this setup and accumulating these tweaks, I managed to get rid of most of the issues that
bothered me during gaming, resulting in a much smoother experience. It finally felt like the gaming VM behaved like a
machine with a 4 core CPU, 16 GB of RAM and an AMD RX 570 inside it.</p>









<figure class="center">
  <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/cpu-before.png">
    <img src="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/cpu-before_hu_f313c6dcbae3d716.webp"
     width="649"
     height="145"
     loading="lazy"
     decoding="async"
     alt="Passmark PerformanceTest CPU results before any tweaks.">

  </a>
  <figcaption class="center">Passmark PerformanceTest CPU results before any tweaks.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/cpu-after.png">
    <img src="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/cpu-after_hu_442aa75b18b01707.webp"
     width="961"
     height="209"
     loading="lazy"
     decoding="async"
     alt="Passmark PerformanceTest CPU results after tweaks.">

  </a>
  <figcaption class="center">Passmark PerformanceTest CPU results after tweaks.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/memory-before.png">
    <img src="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/memory-before_hu_d05a9f2cbaae0f6a.webp"
     width="539"
     height="142"
     loading="lazy"
     decoding="async"
     alt="Passmark PerformanceTest memory results before any tweaks.">

  </a>
  <figcaption class="center">Passmark PerformanceTest memory results before any tweaks.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/memory-after.png">
    <img src="/posts/2021/09/07/diy-cloud-gaming-vfio-parsec-amd/media/memory-after_hu_e2a84ae685917fe.webp"
     width="810"
     height="206"
     loading="lazy"
     decoding="async"
     alt="Passmark PerformanceTest memory results after tweaks.">

  </a>
  <figcaption class="center">Passmark PerformanceTest memory results after tweaks.</figcaption>
</figure>

<p>At this point I&rsquo;d consider the setup to be fantastic for someone who wants to play games with a VFIO setup. Since I was
using this setup over the network with Parsec, I soon ran into more issues, but this time with the GPU.</p>
<h2 id="gpu-issues">
  <a class="heading-anchor" href="#gpu-issues">GPU issues<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Parsec and other similar solutions rely on the host GPU to encode the image into a video stream using the encoder
present on the GPU die itself. You might see this being referred to as <em>hardware encoding</em> in settings. What I didn&rsquo;t
know before trying this setup is that AMD GPU encoders have a reputation
for <a href="https://support.parsec.app/hc/en-us/articles/115002683371-Troubleshooting-Lag-Latency-and-Quality-Issues">just being plain bad</a>:</p>
<blockquote>
<p>If the host has an AMD card, AMD is usually known for having worse encode than NVIDIA and even Intel.
You should be fine at low resolutions. If all guests support H.265 and have it turned on,
you may see better performance than with it off</p>
</blockquote>
<p>And this shows. When trying to stream at 1080p, the result was a stuttery and inconsistent mess. Imagine trying to play
at around 30fps with the frame timings graph resembling a heart rate monitor, that&rsquo;s what it felt like. At 720p, the
experience was so much smoother. Yes, the image quality suffers because of that, but at least it was mostly playable.</p>
<p>I decided to also try out if changing the codec from H.264 to H.265 has a significant impact. I did a quick test in Dirt
Rally due to it having a benchmark loop mode and checked the statistics that Parsec shows. With H.264, I saw encode
latency of about 10ms. With H.265, this latency was now at 8ms. Still not great, but it is technically a ~20%
improvement. The downside of this for my setup is that the client laptop simply does not support hardware accelerated
H.265 decode, which is something that Intel integrated graphics received support for in 7th gen CPU-s.</p>
<p>The GPU seems to also cause some trouble for Parsec, as it would fail to connect occasionally and reports a host encoder
issue. This is usually overcome by rebooting the VM, which can get quite annoying after a couple of times. At other
times, Parsec sometimes just froze during gameplay and caused the client to freeze at 100% CPU usage. Not what I&rsquo;d call
smooth sailing.</p>
<p>Another issue that I noticed by using <a href="https://www.msi.com/Landing/afterburner/graphics-cards">MSI Afterburner</a> is that
the framerate was still not that stable in some games, such as GTA V. After all the fixes and tweaks, there were still
small stutters, even with vsync enabled. I decided to look over AMD Radeon settings to see if a driver feature had an
unintended side effect. I had picked the <em>Gaming</em>
preset because that was what I was using this GPU for, but decided to switch to the <em>Standard</em> mode instead. And just
like that, the stutters were gone! I suspect that the <em>Radeon Anti-Lag</em> feature might have been the cause to this, as
that was one of the main settings that was disabled after switching to the <em>Standard</em> settings preset.</p>
<h2 id="is-it-worth-it">
  <a class="heading-anchor" href="#is-it-worth-it">Is it worth it?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I like a technical challenge and going through all the attempts to get more and more performance out of this setup was
interesting for me. However, it might not be the same way for everyone else. If you still feel like you want to go
through this and learn something along the way, then feel free to use this as a guide on what you can try. Make sure to
also read up on experiences that others have had with these tweaks and always measure your results to see if they had
the intended effect.</p>
<p>For those who just want to play games and not worry too much about getting the expected performance out of your machine,
I&rsquo;d still recommend going with building a separate gaming PC.</p>
<p>If I had to build a machine specifically for this type of workload, then I&rsquo;d make these changes:</p>
<ul>
<li>Replace the CPU with a non-APU model, such as the Ryzen 9 5950X. Due to
the <a href="https://images.anandtech.com/doci/16214/Ryzen9_3800X_Hand_575px_678x452.jpg">physical core layout</a> you could
assign one CPU core complex to the gaming VM and leave everything else to the host. These CPU-s also have a lot of L3
cache, which should help in workloads that require low latency, such as games.</li>
<li>If you&rsquo;re going for a streaming setup, then I&rsquo;d try it first with an NVIDIA GPU. The error code 43 issues are gone
now, making it a viable option with solutions like Moonlight.</li>
<li>More SATA or M.2 slots on the system. This makes passing through storage devices so much easier.</li>
</ul>
<h2 id="future-plans">
  <a class="heading-anchor" href="#future-plans">Future plans<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I&rsquo;m not planning on stopping this adventure just yet. I&rsquo;ve recently looked around for an NVIDIA GPU to do a comparison
against the AMD RX 570 and picked out an NVIDIA GTX 1060, which is from the same era and performance bracket. Should
make for an interesting comparison in both <em>Parsec vs Parsec</em> and <em>Parsec vs Moonlight</em> scenarios.</p>
<p>I&rsquo;m also hoping to eventually move to a more modern client PC that can support H.265 decoding and output at higher
resolutions. Yes, 4K at 60Hz is demanding for a laptop from 2012. Given that the laptop is an older ThinkPad, I expect
that to happen after 2025.</p>
<p>Regarding the storage setup, I&rsquo;ve got input from a friend saying that I might want to try setting up a Samba share on
my &ldquo;NAS&rdquo; VM and host my Steam library and other game files on that. After all, the virtual LAN has managed hit 2-3
Gbit/s in my testing and with L2ARC being persistent in ZFS 2.0, I might be able to take advantage of that as well (
assuming that I even need L2ARC, ARC efficiency is pretty good!). Currently I just have a Syncthing sync set up between
the &ldquo;NAS&rdquo; VM and the gaming VM so that there exists at least a basic backup of all my games.</p>
]]></content:encoded></item><item><title>I've reached the self-hosting endgame</title><link>https://ounapuu.ee/posts/2021/05/23/self-hosting-endgame/</link><pubDate>Sun, 23 May 2021 07:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/05/23/self-hosting-endgame/</guid><description>If all you have is a powerful workstation...</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="I've reached the self-hosting endgame" /><h2 id="setup">
  <a class="heading-anchor" href="#setup">Setup<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>After I had a <a href="/posts/2021/04/02/tech-tip-1/">perfectly functional, quiet and performant server</a> up and running, I fell
victim to my imagination and completely changed my self-hosting setup. Again.</p>
<p>Here it is, in all its glory:</p>









<figure class="center">
  <a href="/posts/2021/05/23/self-hosting-endgame/media/image1.jpg">
    <img src="/posts/2021/05/23/self-hosting-endgame/media/image1_hu_ade80b9e42417ae9.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Find the server.">

  </a>
  <figcaption class="center">Find the server.</figcaption>
</figure>

<p>Well, at least that&rsquo;s what&rsquo;s on the table.</p>









<figure class="center">
  <a href="/posts/2021/05/23/self-hosting-endgame/media/image2.jpg">
    <img src="/posts/2021/05/23/self-hosting-endgame/media/image2_hu_3ea578e613d1eec1.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="There it is.">

  </a>
  <figcaption class="center">There it is.</figcaption>
</figure>

<p>This machine is a true <em>all-in-one</em>: it hosts all my services in a VM while also acting as my main workstation.</p>
<h2 id="specs">
  <a class="heading-anchor" href="#specs">Specs<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>CPU: AMD Ryzen 9 3900X. 12 cores and 24 threads in a consumer platform is absolutely bonkers.</p>
<p>RAM: 32GB DDR4 @ 3200MHz</p>
<p>Motherboard: Gigabyte B450 I Aorus PRO WIFI. It&rsquo;s OK, but oh man are the newer BIOS releases buggy. At least it gives 0
hoots about flashing an older BIOS version.</p>
<p>GPU: AMD RX 560. It gets the job done.</p>
<p>HDD: 2x 12TB WD white-label (WD120EDAZ) drives, shucked from WD My Book external drives.</p>
<p>SSD: 240GB Kingston A1000 NVMe for OS, 2x1TB Samsung 870 EVO SATA SSD for fast solid state storage</p>
<p>PSU: Seasonic Focus <em>something-something</em>. Doesn&rsquo;t really matter, it&rsquo;s reliable and has plenty of power.</p>
<p>Cooling: Noctua NH-D9L on the CPU, 200mm fan at the front and 2x80mm beQuiet fans at the back to keep the system cool.</p>
<p>Case: ThermalTake Core V1. Not the smallest case, but super simple to work in!</p>
<h2 id="why">
  <a class="heading-anchor" href="#why">Why?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Before setting this up, I had three machines running:</p>
<ul>
<li>a laptop that was always on so that there won&rsquo;t be any conflicts with Syncthing.</li>
<li>a server with server workloads</li>
<li>a desktop that I mainly used for work</li>
</ul>
<p>At any point in time, I had at least two machines running and the desktop was fired up for a good part of the day due to
work. Since trying to reduce my electricity usage was one of my goals with going low-power on my server, this sounded a
bit wasteful. At this point I got the brilliant idea of trying to combine this into one machine that does it all, but
before that, I had some concerns. The hardware was simple: just shuck the 12TB drives in there and get some big SSD-s
and partition them, but the software part required some thinking and testing.</p>
<h2 id="the-software">
  <a class="heading-anchor" href="#the-software">The software<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>To keep the work to a minimum, I found that the easiest way to move my setup was to just put the existing server
installation into a VM. I&rsquo;ve had plenty of experience with VM-s so this was not a difficult task, just install libvirt
and all the dependencies will be settled automatically.</p>
<p>The problem is the networking. If I want the VM to show up as a separate machine on the network, I need to add a virtual
network interface as a <code>macvtap</code> device, which means that the desktop and the VM can both connect to the internet and to
other devices on the local network, but the desktop cannot reach the VM directly. There are other solutions, such as the
default NAT-based solution, but with that, forwarding ports is quite tricky to someone not familiar with networking.</p>
<p>To overcome this limitation, I came up with a pretty simple solution: add another network interface to the VM! This
time, the interface was set up as the NAT-based solution. To make this work, I had to make sure that the Debian 10
install was configured to use that interface as well, which meant a little copy-pasting in <code>/etc/network/interfaces</code>. To
make the host connect to this machine using the hostname, I also added an entry to <code>/etc/hosts</code> on the host machine to
route all requests to the hostname via this second virtual network interface.</p>
<p>With this, the main obstacle was resolved and the host machine had no issues connecting to the VM.</p>
<h2 id="the-storage">
  <a class="heading-anchor" href="#the-storage">The storage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Since this machine was also used as a workstation, I had to be a bit clever with my storage setup. The bulk storage in
the form of two 12TB hard drives was 100% managed by the VM.</p>
<p>The 1TB SSD-s were partitioned as such:</p>
<ul>
<li>2x 500GB partitions for my workstation running in BTRFS mirror, since I don&rsquo;t trust ZFS updates on Fedora.</li>
<li>2x 250GB partitions for fast SSD-based ZFS mirror in the VM</li>
<li>2x 250GB free space for overprovisioning.</li>
</ul>
<p>In the event that something does go wrong, it should not have too much of a negative impact either on the host or the
VM. If the drive quality does become a concern, there is always the option to upgrade to PRO series drives that should
have a much better endurance rating.</p>
<h2 id="pros-and-cons">
  <a class="heading-anchor" href="#pros-and-cons">Pros and cons<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With that, the setup was up and running. The VM initially had assigned 6 CPU cores and 8GB of RAM, but lately I&rsquo;ve
decided to assign 12 cores and 16GB of RAM to make the most out of the available resources.</p>
<p>So, how well does it work?</p>
<p>Quite well, in fact. There were some hiccups, though:</p>
<ul>
<li>the latest BIOS update for the motherboard was very buggy, which resulted in the ability to permanently get rid of
boot devices in the boot device selection menu and the annoying issue of getting stuck in POST when rebooting the
machine</li>
<li>the VM would sometimes have issues with networking, which I attempted to fix by treating the NIC-s within the VM as
non-hotpluggable devices. This seems to have done the trick, as I have not had any issues since.</li>
</ul>
<p>With this setup, there are some tradeoffs that you should be aware of.</p>
<p>Pros:</p>
<ul>
<li>Everything runs in one machine with reasonable power usage : ~70 W when idle and monitors off, ~120 W with monitors on
and a light workload</li>
<li>Optimal utilization of resources. Instead of having to upgrade my workstation or server separately, I can just share
the resources and modify limits any time I want. Should I upgrade to 64GB of RAM in the future, I can make some more
available on the server by changing only one configuration parameter in the VM. The same goes for storage. If I were
to upgrade to something bigger and faster, then it will benefit both the workstation and the server workloads.</li>
<li>Easier troubleshooting. In case things go wrong with the server, I don&rsquo;t need to grab an external monitor and hook it
up to the server, the console is accessible via virt-manager on the host.</li>
</ul>
<p>Cons:</p>
<ul>
<li>All eggs in one basket. If your host OS breaks something, then this will affect your server workloads as well.</li>
<li>Noise. While not so bad with noise-cancelling headphones, it can still be annoying when you have hard drives running
at your desk.</li>
<li>Your server workload is dependent on your host OS booting up first, which will require manual input from you if your
host installation is encrypted.</li>
</ul>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This setup worked out better than I expected, with no further issues occurring over a couple of weeks. The availability
issues during restarts are not a concern for me, as this is a hobby to me, and the flexibility and ridiculous amounts of
power this setup has outweighs all the cons.</p>
<p>Let&rsquo;s see how long this setup lasts.</p>
<h2 id="2021-06-28-update">
  <a class="heading-anchor" href="#2021-06-28-update">2021-06-28 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It still works like a charm!</p>
]]></content:encoded></item><item><title>Tech tip: eliminate HDD humming noise</title><link>https://ounapuu.ee/posts/2021/04/02/tech-tip-1/</link><pubDate>Fri, 02 Apr 2021 07:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/04/02/tech-tip-1/</guid><description>Silence your hard drives with this one weird trick! System administrators hate him!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Tech tip: eliminate HDD humming noise" /><p>Anyone that has bought themselves external WD drives from the Elements/My Book/Easystore series are probably familiar
with the acoustic characteristics of the drives. The drives have a loud hum caused
by <a href="https://arstechnica.com/gadgets/2020/09/western-digital-is-trying-to-redefine-the-word-rpm/">WD running the drives at 7200rpm while claiming the drives to be &ldquo;5400rpm-class&rdquo;</a>
and the clacking of the read-write heads is audible as well. In a small space, such as an apartment, the hum is
maddening, especially when you have more than one drive running at the same time.</p>
<p>After running such a setup for months, enough was enough. I bought some sound dampening foam and used that to try to
limit the noise that my setup was making. However, that didn&rsquo;t do much and the before/after noise comparisons didn&rsquo;t
have much of a difference. As a result of this testing, I did have various pieces of acoustic foam left, and after I
noticed that my Lenovo M73 Tiny PC had a similar shape to the WD My Book 12 TB hard drives that I got recently, I had an
idea.</p>









<figure class="center">
  <a href="/posts/2021/04/02/tech-tip-1/media/image.jpg">
    <img src="/posts/2021/04/02/tech-tip-1/media/image_hu_4f0d8b9faae28e72.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Minimum viable server, now with 90% less noise!">

  </a>
  <figcaption class="center">Minimum viable server, now with 90% less noise!</figcaption>
</figure>

<p>I used four pieces of foam and placed them so that I could stack the hard drives on top. This resulted in the humming
noise being completely eliminated. The sound of hard drive read-write heads is still there, but it is so much less
audible now. After this change, I have started hearing the cooling fan more than the hard drives themselves.</p>
<p>This setup could probably be improved by switching around the setup so that the hard drives were at the bottom with the
bottom drive having additional foam or rubber feet below it to support it better. For the time being, I&rsquo;m perfectly
happy with this arrangement, as long as it doesn&rsquo;t fall over.</p>
<h2 id="2021-04-23-update">
  <a class="heading-anchor" href="#2021-04-23-update">2021-04-23 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have now added a fan to the setup!</p>









<figure class="center">
  <a href="/posts/2021/04/02/tech-tip-1/media/image2.jpg">
    <img src="/posts/2021/04/02/tech-tip-1/media/image2_hu_a93d534011079b3e.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Pretty cool, eh?">

  </a>
  <figcaption class="center">Pretty cool, eh?</figcaption>
</figure>

<p>The fan itself is powered by one of the USB ports with the help of a spare sacrificial USB cable and a Noctua omni-join
kit that I had left over.</p>
<p>The drive temperatures are now reading around 42C and 46C.</p>
]]></content:encoded></item><item><title>Whacky setups: seedbox on a wall</title><link>https://ounapuu.ee/posts/2021/03/20/whacky-setups-1/</link><pubDate>Sat, 20 Mar 2021 12:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/03/20/whacky-setups-1/</guid><description>This is what happens when someone takes the meaning of 'brute force' too literally.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Whacky setups: seedbox on a wall" /><p>The Orange Pi Zero is one hell of an SBC. It has served as
a <a href="/posts/2020/07/23/the-little-wifi-ap-that-could/">Wi-Fi access point for months without issues</a>
and as <a href="/posts/2021/02/27/database-optimization-adventures-on-low-end-hardware/">a testbed for playing around with MySQL</a>.</p>
<p>I wanted it to be a useful device again, but had trouble finding an use case for it due to its hardware limitations.
After messing around with my amateur archival work, I had accumulated some data that might be worth keeping around. Due
to my network being quite unreliable and slow, I decided to go with torrents as the main distribution method. I could
have just hosted the torrents on my main server box, which is what I later did anyway, but then I realized that hosting
torrents is a workload that a weak machine could handle just as well.</p>
<p>I took a board that was left over from a shelf, grabbed some twine and nails and banged together this monstrosity:</p>









<figure class="center">
  <a href="/posts/2021/03/20/whacky-setups-1/media/image1.jpg">
    <img src="/posts/2021/03/20/whacky-setups-1/media/image1_hu_16c4fe809499083c.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The setup in all its glory.">

  </a>
  <figcaption class="center">The setup in all its glory.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/03/20/whacky-setups-1/media/image2.jpg">
    <img src="/posts/2021/03/20/whacky-setups-1/media/image2_hu_8a7fb99c0fa20331.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="This setup originally had two 4TB hard drives. Unfortunately one of them was too faulty for even BTRFS to handle.">

  </a>
  <figcaption class="center">This setup originally had two 4TB hard drives. Unfortunately one of them was too faulty for even BTRFS to handle.</figcaption>
</figure>

<p>This brave little machine runs on <a href="https://www.armbian.com/">Armbian</a> and hosts one Transmission instance. This instance
is a mirror for some of the data that I collect as part of my archival effort. The OS
lives on a 120GB Crucial SSD with the help of the <code>nand-sata-install</code> script that Armbian provides, and the data lives
on one 4TB Seagate hard drive that is somehow still working.</p>
<p>The board is pressed against the metal part of an AMD AM4 socket stock cooler with the help of a thick 5mm thermal pad
and solid copper wires taken from an electrical cable. This looks very janky, but the cooling performance is absolutely
fantastic: 30C when idling and not more than 50-60C under the heaviest workloads.</p>
<p>The total power consumption of this setup is typically between the 5-10W range, which isn&rsquo;t the lowest, but still
acceptable. The CPU is a 32-bit one, so let&rsquo;s see if this board can make it to 2038.</p>









<figure class="center">
  <a href="/posts/2021/03/20/whacky-setups-1/media/image3.jpg">
    <img src="/posts/2021/03/20/whacky-setups-1/media/image3_hu_188439b7a186b652.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="All in all, it was just another server on the wall.">

  </a>
  <figcaption class="center">All in all, it was just another server on the wall.</figcaption>
</figure>

<h2 id="2021-04-02-update">
  <a class="heading-anchor" href="#2021-04-02-update">2021-04-02 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The 4TB Seagate HDD decided to start a career in experimental music production and started clicking and not showing up
when connected to a PC. And thus, the seedbox on a wall has been put on pause for now.</p>
]]></content:encoded></item><item><title>How to start your self-hosting adventure: a high-level overview</title><link>https://ounapuu.ee/posts/2021/03/17/how-to-start-your-self-hosting-adventure/</link><pubDate>Wed, 17 Mar 2021 15:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/03/17/how-to-start-your-self-hosting-adventure/</guid><description>Getting started is probably the hardest step.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="How to start your self-hosting adventure: a high-level overview" /><p>Reddit is a great starting point for getting new ideas for your homelab: racks full of machines
in <a href="https://www.reddit.com/r/homelab/">/r/homelab</a>, storage measured in terabytes (or even petabytes) over
at <a href="https://www.reddit.com/r/DataHoarder/">/r/datahoarder</a>, all the different services that people host over at
<a href="https://www.reddit.com/r/selfhosted/">/r/selfhosted</a>. This can be a bit overwhelming for someone just starting out in
this area, which is why I decided to write a small guide on how to start off on your self-hosting adventure.</p>
<h2 id="why-self-host-in-the-first-place">
  <a class="heading-anchor" href="#why-self-host-in-the-first-place">Why self-host in the first place?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Hobbyists and professionals have a lot of different reasons for self-hosting services. These include (but are not
limited to):</p>
<ul>
<li>it&rsquo;s an excuse to play around with computer hardware and rationalize the purchase of thousands of dollars of hardware</li>
<li>reduce reliance on <a href="https://en.wikipedia.org/wiki/Big_Tech">&ldquo;big tech&rdquo;</a></li>
<li>the services solve an actual problem for the user (home automation, secure file storage, backups etc.)</li>
<li>learning new tech and solutions that otherwise have not come up during their day-to-day work</li>
</ul>
<p>Regardless of the specifics, the main part of the self-hosting experience is to just have fun and work on challenges
that you find interesting.</p>
<h2 id="step-0-find-a-problem-to-solve">
  <a class="heading-anchor" href="#step-0-find-a-problem-to-solve">Step 0: find a problem to solve<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>One of the best motivators for setting up your homelab/self-hosting setup is to solve a real problem that you have.</p>
<p>Do you want to automate your home with <a href="https://www.home-assistant.io/">HomeAssistant</a>?</p>
<p>Or do you want your family to be able to back up their valuable photos and videos to your server
using <a href="https://nextcloud.com/">Nextcloud</a>?</p>
<p>Or do you want to share your media collection with your family and friends using <a href="https://jellyfin.org/">Jellyfin</a>?</p>
<p>It doesn&rsquo;t really matter what solution you end up using or how you do it, as long as it is a secure solution and that
solves your original problem without creating 10 additional ones.</p>
<h2 id="step-1-find-a-place-for-running-your-software">
  <a class="heading-anchor" href="#step-1-find-a-place-for-running-your-software">Step 1: find a place for running your software<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Once you have a problem that you are going to solve, you will need to also find a home for your project to live in. For
this, you have a lot of different options:</p>
<ul>
<li>using a virtual machine at a cloud service provider (DigitalOcean, Linode etc.). Performance is not the best and
beefier configurations can be quite expensive, but this is a reliable option with a fast network.</li>
<li>renting a server from a service provider (example: Hetzner). More performant than a virtual machine at most cloud
service providers, but probably more expensive as well. Usually comes with a fast network.</li>
<li>an old laptop that you have collecting dust on your shelf. Not the fastest or the quietest option, but it does not use
a lot of power.</li>
<li>an old desktop PC. Probably plenty fast for any task that you can throw at it, but its power usage is higher compared
to laptops.</li>
<li>a tiny desktop PC. Low power usage, but can pack quite a punch. For inspiration, check
out <a href="https://www.servethehome.com/introducing-project-tinyminimicro-home-lab-revolution/">Project TinyMiniMicro</a>
by ServeTheHome.</li>
<li>a single-board computer, such as a Raspberry Pi or alternatives. Plenty of performance for most workloads, uses very
little power (5-15W generally) and silent as well.</li>
<li>a second-hand rack-mounted server. Probably quite performant, but uses a lot of power and is very noisy.</li>
<li>a NAS box from one of the more popular providers (Synology, QNAP, TerraMaster etc.). Useful for when you need a lot of
storage on your machine or something that <em>just works</em>.</li>
</ul>
<p>Your choice will likely be affected by other factors as well:</p>
<ul>
<li>your home internet connection. If your ISP does not allow opening ports or if your upload/download speeds are not that
great, then using a cloud service provider or renting a server might be a better option for you.</li>
<li>living in a small apartment will likely rule out noisy solutions, such as full-blown rack-mounted servers or powerful
desktop PC-s.</li>
<li>if all you want to do is local testing, then a virtual machine on your already existing desktop/laptop PC might be a
better fit, as it does not require you to buy any new/used hardware.</li>
<li>reliability and price of electricity. In some countries, running a server in your home might result in a huge power
bill or might not be possible at all due to the power grid being unreliable.</li>
</ul>
<p>The workloads that you plan on running will also have an effect on your chosen approach. You will need to take into
account the resources that your workload requires. It does not make much sense to get a rack-mount server for hosting
your Wordpress blog if a Raspberry Pi can do the same job just as well. On the other hand, running a CPU-heavy service
like Jellyfin on a Raspberry Pi will be a painful experience when compared to running it on a desktop PC or an
enterprise-grade server. If your service will be used by a high number of users, then you might want to opt for a more
powerful machine.</p>
<p>Some solutions may also benefit from faster, SSD-based storage. Loading a lot of smaller files or running a big database
off of hard drives will be noticeably slower than running them off of fast SSD-s.</p>
<p>There is no <em>one size fits all</em> solution. It&rsquo;s better to do a little bit of initial research and use the right tool for
the job. If in doubt, ask for help from someone more experienced.</p>
<h2 id="step-2-find-the-software-solution-that-fits-your-use-case-the-best">
  <a class="heading-anchor" href="#step-2-find-the-software-solution-that-fits-your-use-case-the-best">Step 2: find the software solution that fits your use case the best<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Just like with hardware, there is also a lot of choice when it comes to software.</p>
<p>Some solutions are pretty low-level and require setting up the OS and the services manually. This is not very
user-friendly, but it offers the most potential for learning about your system and how to manage it. This approach will
likely require you to learn new things and pay more attention to automating common tasks (updates, monitoring, backups)
and making sure that everything is secure (no weak passwords, services properly isolated, regular and frequent updates
etc.). If something goes wrong, then you will need to fix it yourself, but at least you have all the tools and knowledge
to do so.</p>
<p><strong>Example:</strong> Debian with ZFS for your main storage and services running using Docker or Podman (my personal preference).</p>
<p>There are also solutions that cater to people who just want to get work done. These solutions usually provide the user
with a web-based user interface that can manage the system and any services that run on it. Do you want to set up your
very own Wordpress blog? Just click this button and you will soon be set up with one without having to even know what
the hell a &ldquo;Docker&rdquo; is. The downside of this approach is that when things go wrong, you will still need to familiarize
yourself with the inner workings of the system. Troubleshooting issues with no preparation and learning new things under
stressful circumstances is not very fun.</p>
<p>Cloud service providers have also started offering <em>one-click</em> solutions to setting up the more popular services. your
very own Minecraft server is just a click away!</p>
<p><strong>Examples:</strong></p>
<ul>
<li>a NAS box from Synology that is aimed towards consumers</li>
<li>VM provided and set up by Linode using a one-click solution in their web UI.</li>
</ul>
<p>And then there are solutions that fit in somewhere in-between. Solutions
like <a href="https://www.truenas.com/">TrueNAS (formerly FreeNAS)</a>
and <a href="https://www.openmediavault.org/">OpenMediaVault</a> are made for users that can probably set things up themselves as
well, but are just too lazy to do it. Using these solutions is not in any way worse than the alternatives. If it solves
a problem and fits your use case, then go ahead and use it! Just keep in mind that you might need to peek under the hood
when there are issues where the GUI cannot help you out.</p>
<p>As always, if in doubt, ask for assistance. It is perfectly fine for you to pick one of the user-friendlier options
first and dig deeper once you feel more comfortable. Self-hosting is not a race, you can do everything at your own pace.</p>
<h2 id="step-3-managing-your-setup">
  <a class="heading-anchor" href="#step-3-managing-your-setup">Step 3: managing your setup<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Once you have everything up and running, there are some topics that you really should pay attention to in order to avoid
big problems down the line.</p>
<h3 id="backups">
  <a class="heading-anchor" href="#backups">Backups<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>If the only copy of your files lives on your NAS and something should happen to them (accidental delete, hard drives
suddenly die, you get hit by ransomware etc.), then you are in a world of hurt. Having backups is a mandatory part of
your self-hosting adventure. A mix of automated and manual backups is better than having no backups at all.</p>
<p>Some ideas for backups:</p>
<ul>
<li>
<p>external hard drive attached to your server that receives automated backups that run on an schedule. Just make sure
that any failures during the backup will be communicated to you (over e-mail, for example). It&rsquo;s also a good idea to
occasionally check if the last backup was successful or not. Downside of this approach is that since this drive is
still connected to the server, it is subject to other events that can shred your data (ransomware, power surges etc.).</p>
</li>
<li>
<p>offline backups that you will manually run on a regular schedule. Example: copying all files from the server to an
external hard drive on the 1st day of each month. If you accidentally delete all files on your server or a piece of
malware does this for you, or if your server is toast due to a power surge, you will still have a copy of the data
that cannot be affected by those kinds of issues.</p>
</li>
<li>
<p>snapshots. While technically not a backup, snapshots do help against accidental deletes. Depending on your setup, you
might be able to retrieve files deleted a week ago if you keep snapshots of your data for the last 30 days.</p>
</li>
<li>
<p>a hard drive at your friends house. Helps protect against the worst case scenario where your house burns down.</p>
</li>
<li>
<p>(encrypted) backups to cloud storage providers, such as Backblaze, OneDrive or Google Drive. It will require a monthly
subscription, but at least you will likely have a copy of the file <em>somewhere</em>. Just keep in mind that if you should
get locked out of the service or fail to pay for it, then you might not be able to access the data hosted at that
service.</p>
</li>
</ul>
<h3 id="security">
  <a class="heading-anchor" href="#security">Security<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>If you are exposing a service to the wild wild west that is the internet, then you will be a target. Automated scanners
will poke your services and if they find a vulnerability, they will use it. To prevent the worst, consider the
following:</p>
<ul>
<li>
<p>keep everything up to date. Don&rsquo;t forget that for some updates to apply (example: kernel updates), you <em>need</em> to
restart the machine. For other services (example: ssh), they can be restarted without restarting the whole machine.
Regular updates will help prevent most security issues.</p>
</li>
<li>
<p>only expose services that you absolutely need to expose. With something like a web server, you really don&rsquo;t have a lot
of choice here, but with services aimed towards a known set of users, you can limit the exposed surface area by using
a VPN or enforcing other restrictions (whitelisted IP addresses, fail2ban to block most intrusion attempts, etc.).</p>
</li>
<li>
<p>make sure that your configuration is correct. A lot of intrusions are caused by configuration issues that usually end
up with a service being exposed to the web without any passwords or other protections set up. It&rsquo;s a good idea to
check if you are accidentally exposing too much by checking what others are seeing when they try to connect to your
service.</p>
</li>
<li>
<p>try to set up your services so that you are prepared for an intrusion. If the attacker is able to take control of
service X, but it is completely isolated from other services and devices on the network, then the damage they can do
is likely limited.</p>
</li>
</ul>
<h3 id="monitoring">
  <a class="heading-anchor" href="#monitoring">Monitoring<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h3>
<p>Your setup will likely have issues. Hard drives might die, or the CPU might be overheating due to years of dust
accumulation, or one service might be using up all the available resources, causing others to slow down as well. A
better understanding of what your system is doing will help out a lot here.</p>
<p>Cloud hosting service providers usually provide at least a basic level overview of your resource usage: CPU, RAM, disk,
network etc. If you are running your own machine, then you will need to figure this out on your own.</p>
<p>To understand what your system is doing, a tool like <a href="https://www.netdata.cloud/">Netdata</a> is a good starting point. If
your server slows down, then you can most likely pinpoint the reason by looking at the resource indicators.</p>
<p>It is not realistic for you to keep an eye on all the indicators all the time, so having some kind of alerting set up is
also a great idea. Events, such as a hard drive starting to throw errors, the CPU usage being at 100% for more than an
hour, or a service not being reachable, are all something that you might be interested in hearing about.</p>
<p>You don&rsquo;t have to monitor everything and have alerts set up to catch everything, but it is a great starting point for
responding to issues proactively. Ending up with all your data lost because you did not hear about hard drive failures
is not a great situation to be in.</p>
<h2 id="what-next">
  <a class="heading-anchor" href="#what-next">What next?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>If you have reached this point, then you are probably aware of most of the topics that will come up during your
self-hosting adventure. You will encounter issues that will be specific to the approach that you have chosen at the
hardware and software steps, but that&rsquo;s perfectly normal. Most of these issues have solutions that are one search away,
and if you have trouble figuring something out, then feel free to ask for help!</p>
<p>If you need new ideas, then check out the subreddits mentioned at the start of this post, you might find some gems in
there! Do keep in mind that you will likely end up in an endless loop of building something, being happy with it for a
week and finding something else to try out. It&rsquo;s really fun, though.</p>
]]></content:encoded></item><item><title>My server setups throughout the years</title><link>https://ounapuu.ee/posts/2021/03/17/server-setups-throughout-the-years/</link><pubDate>Wed, 17 Mar 2021 10:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/03/17/server-setups-throughout-the-years/</guid><description>From repurposed old PC-s to the elusive _minimum viable server_.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="My server setups throughout the years" /><p>My self-hosting adventure started during my university days. Once I actually had money to buy myself a decent used laptop
(ThinkPad T430) that had more than 3GB of RAM that my ThinkPad T60 had, I could use some of my older hardware as
testbeds for any of the stupid ideas that I had. For someone that liked to learn more about Linux and wanted any excuse
to play around with hardware, something like a RAID0 setup over 4 80GB Samsung hard drives on an old PC setup sounded great.</p>
<p>I also had a small collection of data that I had on an 1TB external hard drive, and I wanted to also have backups of
the data that lived on my laptop. This was the main motivation for setting up a machine that would serve as a NAS and
a testbed for anything that I wanted to try out.</p>
<h2 id="the-first-box-amd-athlon-64-x2-4200-based-pc">
  <a class="heading-anchor" href="#the-first-box-amd-athlon-64-x2-4200-based-pc">The first box: AMD Athlon 64 X2 4200+ based PC<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>At this point in time, I didn&rsquo;t really have any names for my systems. They were simply named by the model of the machine
or whatever else I had in mind.</p>
<p>One of the first &ldquo;server&rdquo; builds that I built was based on some old parts I had lying around. The CPU was from an old
family PC that we got in 2006, and to this date, it is the only surviving component from that build. The motherboard
was from a place that collected old hardware and resold some of it and if I remember correctly, it was the <em>abit KN9 Ultra</em>.
AM2 socket, DDR2, 6 SATA ports, all that good stuff. This was coupled with 4GB of DDR2 memory. Not much, but it is a start.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/amd.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/amd_hu_b46af76ea55c117b.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The heart of the system. It wasn&#39;t fast nor power efficient, but at least I had something.">

  </a>
  <figcaption class="center">The heart of the system. It wasn&#39;t fast nor power efficient, but at least I had something.</figcaption>
</figure>

<p>The details regarding the hard drive situation are a bit hazy, but at least initially it hosted whatever drives I had around.
At some point I managed to buy 8x 500GB hard drives to test out ZFS on a big array. This was mainly inspired by <a href="https://www.reddit.com/r/buildapc/comments/6cn1wk/build_complete_alice_a_32tb_server_in_an_nzxt/">the glorious
32TB server build in an NZXT S340 case</a>
that someone showed off in Reddit. I&rsquo;m still surprised that it was acceptable for me to be in the same room as that
monstrosity.</p>
<p>This setup ran well for a while and there weren&rsquo;t any hardware issues with this setup. Drives were OK, speed was acceptable,
and ZFS did its job well, since this was all a big RAID-Z3 array. I even removed two drives temporarily to put in a GPU
at one point and ZFS did not complain. After putting the drives back in, the drives were resilvered and all was good.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-v2.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-v2_hu_25c122b165ff26a8.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The server box running a more sensible setup of less than 8 hard drives.">

  </a>
  <figcaption class="center">The server box running a more sensible setup of less than 8 hard drives.</figcaption>
</figure>

<h2 id="the-engoodening-of-my-server-amd-ryzen">
  <a class="heading-anchor" href="#the-engoodening-of-my-server-amd-ryzen">The engoodening of my server: AMD Ryzen<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>2017-2018 was wild in the world of CPU-s. AMD came in with some well-designed CPU-s that provided a much better value
proposition than the competing Intel CPU-s at the time. The value was insane: double the cores for the same price!
It didn&rsquo;t take much for me to be convinced that the next server build will be an AMD Ryzen based machine, and as soon as
I had the resources, I got myself parts for doing that upgrade.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-ryzen-1.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-ryzen-1_hu_9f206dd1c6dfd4f5.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Picture taken moments before a lot of fun was had.">

  </a>
  <figcaption class="center">Picture taken moments before a lot of fun was had.</figcaption>
</figure>

<p>The build wasn&rsquo;t without hiccups, though. I discovered that cats <em>really</em> like playing around with screws and walking on
all the expensive computer parts that took up half of the free space in the apartment. Nevertheless, I managed to complete
the build.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/hdd-migration.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/hdd-migration_hu_f7eae416a9114eb9.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="How to migrate from an 8x HDD setup to something more sensible.">

  </a>
  <figcaption class="center">How to migrate from an 8x HDD setup to something more sensible.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-ryzen-2.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/amd-ryzen-2_hu_5657a28acdf54d9.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="New parts, new drives.">

  </a>
  <figcaption class="center">New parts, new drives.</figcaption>
</figure>

<h2 id="laptop-as-a-server">
  <a class="heading-anchor" href="#laptop-as-a-server">Laptop-as-a-server<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Due to reasons that have no rational explanations, I started looking into switching out this perfectly working server
machine into something more power efficient. The CPU sat idle most of the time and I figured that I could use the machine
somewhere else.</p>
<p>And thus, one of the stupidest server builds was born: a ThinkPad X230 serving as a server, with two 4TB WD Red hard drives
attached over USB 3.0, running BTRFS RAID1. I do not have pictures of the setup, but this was pretty much it. I learned
soon after that cats like climbing on things and that they have no understanding of the amount of force that is required to
temporarily disconnect the USB 3 cable from the laptop. This is the part where BTRFS failed on me and I actually lost data
in the array. Luckily I had <em>working</em> backups.</p>
<p>Not long after this incident, I started looking for alternatives.</p>
<h2 id="low-power-but-still-somewhat-usable">
  <a class="heading-anchor" href="#low-power-but-still-somewhat-usable">Low power, but still somewhat usable?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My search criteria was quite simple:</p>
<ul>
<li>low power (ruled out any desktop builds)</li>
<li>x86 based (no OS lock-in)</li>
<li>hosts at least 2 drives over SATA</li>
<li>reasonably priced</li>
</ul>
<p>The closest match I could find was the <a href="https://www.terra-master.com/global/f2-221.html">TerraMaster F2-221</a>. It has a
low-power Intel CPU, standard UEFI implementation, fits two drives and has two SATA ports. The only part that it really
didn&rsquo;t fit under well was the reasonable cost aspect, but it was still much more affordable than the alternatives.</p>
<p>Around this time I also discovered the world of <a href="https://www.reddit.com/r/DataHoarder/comments/7fx0i0/wd_easystore_8tb_compendium/">shucking</a>.
I got myself two 8TB WD MyBook drives and used them in this build. However, what I did not take into account was the noise.
These 8TB drives were much louder than the 4TB WD Red drives that I used previously, and allegedly this is due to WD labelling
these drives as &ldquo;5400-rpm class&rdquo;, even though they actually run at 7200 rpm. The TerraMaster NAS unit had no vibration
dampeners or other methods to isolate the noise, so I had to stick it in a closet.</p>
<p>The TerraMaster build was otherwise great. I could upgrade the RAM to 10GB using the available DDR3 SODIMM slot on the
board, and the services that ran on it were fine. This thing could even run Jellyfin, assuming that you utilized the
integrated GPU to provide hardware acceleration for transcoding video.</p>
<p>However, there were some limitations for this setup:</p>
<ul>
<li>OS lives on an USB drive. Generally fine, but depending on your setup you could pick between internal USB 2.0 ports or
one of the USB 3.0 ports at the back.</li>
<li>When you have lots of small files and a database on the system as well, the lack of SSD base storage became quite
painful. You could do it over the available USB 3.0 ports on the back, but that&rsquo;s it.</li>
</ul>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/terramaster.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/terramaster_hu_6c7842e87877151f.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Yes, that is an mSATA drive in an USB enclosure stuck inside the TerraMaster chassis.">

  </a>
  <figcaption class="center">Yes, that is an mSATA drive in an USB enclosure stuck inside the TerraMaster chassis.</figcaption>
</figure>

<h2 id="back-to-the-desktop">
  <a class="heading-anchor" href="#back-to-the-desktop">Back to the desktop<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Due to a combination of me getting two ITX builds and having workloads that are performance-sensitive (PostgreSQL,
Nextcloud, Jellyfin), I decided to go back to where I started from and put the setup back into a desktop case.
For that purpose, I picked the <a href="https://uk.thermaltake.com/core-v1.html">Thermaltake Core V1</a>, mainly due to how easy it
is to build in it and it having room for 2x8TB hard drives and 2x 2.5&quot; SSD-s.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/desktop-server-1.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/desktop-server-1_hu_6a6e46bf345af9ea.webp"
     width="600"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Clean and performant server setup.">

  </a>
  <figcaption class="center">Clean and performant server setup.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/desktop-server-2.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/desktop-server-2_hu_db4e56b4e1d94ad8.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="For future historians: yes, even servers had RGB in 2020.">

  </a>
  <figcaption class="center">For future historians: yes, even servers had RGB in 2020.</figcaption>
</figure>

<p>This box was very fast. Too fast, in fact. It also used quite a lot of power. 70-120W doesn&rsquo;t sound like much, but when
this box is supposed to run for 24 hours a day, this really adds up. I had reached my storage target, the performance was
acceptable and everything was working, which meant that the next logical step is to change the setup and hit some limits
again.</p>
<h2 id="quest-for-low-power-usage">
  <a class="heading-anchor" href="#quest-for-low-power-usage">Quest for low power usage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>At this point, I had made it a game for myself to try to go as low as possible with the power usage of my setup while also
running my workloads at an acceptable performance level. From my previous meddling, I had a ThinkPad T430 that now boasts
16GB of RAM and a 4-core Intel i7 3820QM quad-core CPU, which is plenty of performance. This laptop also houses up to three
SSD-s, which meant that having performant storage around over SATA was also not an issue. The main storage (2x 8TB)
was attached over USB 3.0. Not the best solution, but ZFS has handled these kinds of setups very well in my past
experience.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/t430-server.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/t430-server_hu_7e083d43ceb10ec.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="Sure, it&#39;s low power, but the cables are a mess.">

  </a>
  <figcaption class="center">Sure, it&#39;s low power, but the cables are a mess.</figcaption>
</figure>

<h2 id="can-we-go-even-smaller">
  <a class="heading-anchor" href="#can-we-go-even-smaller">Can we go even smaller?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Recently I have learned about tiny form factor machines produced by big OEM-s, such as Dell, HP and Lenovo. These
machines are very compact, but can pack quite a punch with a desktop-level CPU and the ability to put in 16+GB of RAM
while being powered by a laptop power supply. The only downside of these builds is that the internal storage can be limited
to 1-2 drives (SATA or M.2 form factor) and not all USB ports might be USB 3.0.</p>
<p>Once I stumbled upon one offer for a Lenovo M73, I knew that I had to try this kind of setup out. Initially I was thinking
of using such a machine for media center purposes, but after I accidentally configured one too many UEFI settings for my
ThinkPad X230 in the advanced BIOS settings, I needed a replacement laptop. And thus, the ThinkPad T430 based server
was replaced by the M73. I did have to limit the CPU power usage using <code>intel_pstate</code> driver and the USB 3.0 ports
needed a bit of bending so that they aren&rsquo;t loose, but other than that it has been smooth sailing.</p>
<p>This is where the story ends for now. The machine takes about 13-15W when idling, and with 4 8TB external hard drives
attached, the typical power usage is between 40-55W. I am planning on replacing the 4 drives with 2 high-capacity drives,
something like a WD Elements/MyBook 14TB once those go on sale.</p>









<figure class="center">
  <a href="/posts/2021/03/17/server-setups-throughout-the-years/media/lenovo-m73.jpg">
    <img src="/posts/2021/03/17/server-setups-throughout-the-years/media/lenovo-m73_hu_e5e6ff1adfec4343.webp"
     width="1067"
     height="800"
     loading="lazy"
     decoding="async"
     alt="The current setup in all its glory. Don&#39;t worry, the cable mess is temporary until I get a PSU that can supply all the drives at once.">

  </a>
  <figcaption class="center">The current setup in all its glory. Don&#39;t worry, the cable mess is temporary until I get a PSU that can supply all the drives at once.</figcaption>
</figure>

<h2 id="future-plans">
  <a class="heading-anchor" href="#future-plans">Future plans<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This is probably where the setup changes will stop for a while. I occasionally play around with some alternative setups to try
to go even lower (Raspberry Pi 4), but so far this setup has proven to be the <em>minimum viable server</em>. It does everything
that I need, the power usage is low and it has room for expandability with regards to services that I can run on it.</p>
<p>If I had to start from scratch, then I would probably opt for an <a href="https://www.asrock.com/nettop/AMD/DeskMini%20X300%20Series/index.asp">AsRock Deskmini X300</a>.
It has the same power efficiency benefits, but you could install a more powerful CPU, a lot of RAM and up to 4 SSD-s,
two of which can be NVMe drives.</p>
<p>The bulk storage would still be over USB 3.0, but that comes with its own benefits:</p>
<ul>
<li>you can not go over a reasonable amount of drives, meaning that your wallet will be happy.</li>
<li>you do not need to shuck the drives, you can use them as-is and get warranty service without issues.</li>
</ul>
<p>This has been my self-hosting journey throughout the years. I hope that it was at least somewhat interesting and maybe
gave you some ideas to test out on your own.</p>
]]></content:encoded></item><item><title>My attempt at archiving nfscars.net</title><link>https://ounapuu.ee/posts/2021/03/01/my-attempt-at-archiving-nfscars.net/</link><pubDate>Mon, 01 Mar 2021 09:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/03/01/my-attempt-at-archiving-nfscars.net/</guid><description>Nostalgia is one hell of a drug.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="My attempt at archiving nfscars.net" /><p>2025 June update: the contents of my archive are now easily accessible over
at <a href="https://www.nfs-cars.com/">nfs-cars.com, a read-only static website that hosts content that was previously on nfscars.net.</a>
I&rsquo;m not affiliated with that website, but I&rsquo;m very happy that it exists!</p>
<h2 id="background">
  <a class="heading-anchor" href="#background">Background<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>My mother once had a laptop: the Compaq Armada 1592DT. It came with Windows ME which later got &ldquo;upgraded&rdquo; to Windows 98
SE
after I managed to completely screw up the OS, a whopping 96MB of RAM and a hard drive that probably wasn&rsquo;t much larger
than 1-3GB. It wasn&rsquo;t powerful or anything, but some of my earliest memories of playing video games on that thing were
related to Sports Car GT and Need for Speed III Hot Pursuit. Yes, both were demos, and the performance was probably in
the 10-20FPS range, but it was still great for a younger me. That laptop eventually got replaced by a Windows 98 based
desktop which wasn&rsquo;t a lot better with its 64MB of RAM, but it could play RuneScape (barely) and also Need for Speed
III.</p>
<p>Need for Speed III Hot Pursuit holds a very special place in my heart. It looked great at the time, the police chases
were
fun and challenging, the soundtrack was fantastic and the track featured in the demo (Rocky Pass) is still something I
could probably draw up from memory, assuming that I could draw. At some point I discovered that it is possible to mod
the game to include new cars and tracks, which resulted in ridiculous speeds, cars that could absolutely destroy the
police cars, and lots and lots of game crashes. One of the sources for these mods
was <a href="https://www.nfscars.net/">nfscars.net</a>.</p>
<h2 id="nfscarsnet">
  <a class="heading-anchor" href="#nfscarsnet">nfscars.net<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Depending on when you will be reading this, nfscars.net is/was a website that hosts/hosted thousands cars, tracks and
other
mods for various Need for Speed titles. In 2020, I decided to check this site out again to see if it is still
operational.</p>
<p>The last post referred to an &ldquo;upcoming&rdquo; NFS title that was already released a year ago.</p>
<p>The link to the forums resulted in an error page being shown.</p>
<p>Should the site suddenly disappear without any warning, all the content would be lost. Since I have a small datahoarding
bug, I decided to take matters into my own hands and do my best to archive the contents of the site. That, and nostalgia
for the old Need for Speed titles was what pushed me to start this archiving adventure.</p>
<h2 id="initial-efforts">
  <a class="heading-anchor" href="#initial-efforts">Initial efforts<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Before trying any fancy technical solutions to crawl the site and get all of the assets that way, I decided to start
from
the source and tried contacting the site owner to arrange the download of the assets. That did not work out at all,
since the contact e-mails were either not active or the inboxes were full.</p>
<p>I signed up for the site and tried to message some user accounts which hopefully were related to someone who was in
charge.
No dice.</p>
<p>There is a small chatroom on the site named &ldquo;Shoutbox&rdquo;, so I tried asking about the site owners there. It seems that a
couple of users are still occasionally chatting there, mainly about random topics and spammy users. Unfortunately none
of the users there - even the moderators - could not assist with setting up a backup of the site.</p>
<p>With the domain (potentially) expiring on 2021-05-02, I felt like I had to act now, because the site was probably
running
on borrowed time.</p>
<h2 id="technical-solutions">
  <a class="heading-anchor" href="#technical-solutions">Technical solutions<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I checked a selection of solutions for performing a crawl on the site and decided
on <a href="https://github.com/internetarchive/heritrix3">Heritrix</a>,
mainly due to this being backed by the <a href="https://archive.org/">Internet Archive</a>.
If they cannot get archiving right, then who can?</p>
<p>Setting up Heritrix turned out to be quite a hassle. There does not seem to be a quick guide that you can follow to
get started in 5 minutes. After stumbling around, learning the config file format and understanding that the best way
to configure crawls was to do it externally with a text editor, I was set up to launch my first crawl. Even then, I hit
some roadblocks:</p>
<ul>
<li>The crawl was slow. I understand that Heritrix is just trying to be polite here, but if you have millions of URL-s to
crawl and the site might go down at any moment, then time really isn&rsquo;t on your side.</li>
<li>Checkpointing is supported, but for some reason the default configuration does not enable it. If the machine that you
are running this on should restart, then your crawl will be stopped and you cannot resume at that point, you can only
start
over.</li>
<li>Heritrix is based on Java, which means that <em>theoretically</em> it should run on anything that runs Java, such as an ARM
CPU based SBC. However, I ran into weird <code>java.nio</code> related issues with symlinking on those platforms and I just could
not get them resolved.</li>
<li>If you run too many crawls at once, then Heritrix is perfectly capable of killing your LAN by using up all the
available
connections. It managed to rack up 16000+ active connections, which hit the 16384 connection limit on my
consumer-grade
router. That was not fun to debug.</li>
<li>Automatically continuing crawls from a checkpoint on system startup requires you to use the Heritrix API, which isn&rsquo;t
too complicated, but I just wish that this was another feature that it supported out of the box.</li>
</ul>
<p>After messing up a couple of times and trying again, I finally managed to complete a crawl of the site. This only took 6
months,
where the crawl itself ran for 3 months. <strong><em>MONTHS!</em></strong></p>
<h2 id="what-the-hell-is-a-warc">
  <a class="heading-anchor" href="#what-the-hell-is-a-warc">What the hell is a WARC?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Heritrix collects the results of the crawl into a special format
called <a href="https://en.wikipedia.org/wiki/Web_ARChive">WARC</a>,
which it then compresses, resulting in lots of little <code>.warc.gz</code> files. If you extract one of these, you will end up
with
a <code>.warc</code> file.</p>
<p>To extract files from a WARC file, you
need <a href="https://wiki.archiveteam.org/index.php/The_WARC_Ecosystem">one of these tools listed here</a>.
After trying a couple, I decided to go with <a href="https://github.com/chfoo/warcat">warcat</a> since it seemed to mostly work and
it supported combining smaller WARC files into bigger ones and extracting the contents.</p>
<p>Depending on the size of the site, the extracting process might take a while. Crawls can contain thousands or even
millions
of small little files, and if you are using hard drives for storing these, then it will be slow. I have not done testing
on an SSD, but it will probably be much faster due to its superior random I/O performance.</p>
<p>Once I had extracted the contents, I did some checking to see if the assets that I care about are present in the crawl.
Did a file search for a modded car in Need for Speed III.</p>
<p>No results.</p>
<p>Okay, that&rsquo;s odd. Tried it with another file name.</p>
<p>No results.</p>
<p>Well, what <em>do</em> we have? I checked the extracted contents using <code>ncdu</code> and found that while Heritrix managed to grab a
lot
of the webpages and the images from the galleries, it failed to download files, such as .zip and .rar files that contain
the modifications themselves.</p>
<h2 id="getting-the-final-pieces-of-the-puzzle">
  <a class="heading-anchor" href="#getting-the-final-pieces-of-the-puzzle">Getting the final pieces of the puzzle<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I started investigating the download functionality of the site. On every page load, the download link would have a new
identifier attached to it. Upon clicking on it, the download would start. If you wait too long, then the download link
would expire.</p>
<p>Firefox has a handy feature where you can copy the request into a <code>curl</code> command. I did that, added some parameters to
it
so that it would use the filename that comes from the response header and made it save the file to disk. It worked!</p>
<p>Now I had to figure out how to collect all of these download links. The site has sections for each game, which is also
reflected in the URL. However, I found that when you navigate to the page of a mod and change the numerical ID at the
end,
you could cycle through all the cars, tracks and other tools for <em>all</em> games, even if the URL was technically referring
to one game in the series.</p>
<p>After bashing around for a while, I came up with this masterpiece:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>cd /your/download/destination <span style="color:#f92672">||</span> exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> index in <span style="color:#f92672">{</span>1..18050<span style="color:#f92672">}</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Index at </span>$index<span style="color:#e6db74">, starting.&#34;</span>
</span></span><span style="display:flex;"><span>  filePath<span style="color:#f92672">=(</span><span style="color:#66d9ef">$(</span>curl --silent https://www.nfscars.net/need-for-speed-hot-pursuit/1/files/view/$index/ -H <span style="color:#e6db74">&#39;Cookie: csrftoken=XXX; sessionid=YYY&#39;</span> | grep -oE <span style="color:#e6db74">&#34;files/download/send/[0-9]+/[0-9a-zA-Z]+&#34;</span><span style="color:#66d9ef">)</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;File path: </span>$filePath<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Making directory </span>$index<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  mkdir -p <span style="color:#e6db74">&#34;</span>$index<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Going into directory </span>$index<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  cd $index
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> path in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>filePath[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Starting download on path https://www.nfscars.net/</span>$path<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    curl --silent <span style="color:#e6db74">&#34;https://www.nfscars.net/</span>$path<span style="color:#e6db74">&#34;</span> -H <span style="color:#e6db74">&#39;User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0&#39;</span> -H <span style="color:#e6db74">&#39;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&#39;</span> -H <span style="color:#e6db74">&#39;Accept-Language: en-US,en;q=0.5&#39;</span> --compressed -H <span style="color:#e6db74">&#39;Connection: keep-alive&#39;</span> -H <span style="color:#e6db74">&#39;Referer: https://www.nfscars.net/need-for-speed-hot-pursuit/1/files/view/1/&#39;</span> -H <span style="color:#e6db74">&#39;Cookie: csrftoken=XXX; sessionid=YYY&#39;</span> -H <span style="color:#e6db74">&#39;Upgrade-Insecure-Requests: 1&#39;</span> -OJ
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Download </span>$path<span style="color:#e6db74"> done.&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  cd /your/download/destination 
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Back in home dir. Index </span>$index<span style="color:#e6db74"> end.&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>Not the prettiest script around, but it did the trick. In a day or so the assets were downloaded and you could use the
index to connect these to a page that is contained in the crawl.</p>
<h2 id="results">
  <a class="heading-anchor" href="#results">Results<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>All this effort would be for nothing if I didn&rsquo;t share my results, so I decided to pack these up and serve them for
anyone
that wants to keep a backup of at least one part of Need for Speed history.</p>
<p>The archived content can be found <a href="https://archive.org/details/nfscars.net.2020.">on the Internet Archive</a>.
<a href="https://archive.org/details/nfscars.net.2021">Here&rsquo;s a newer crawl from 2021.</a></p>
<p>The torrent files are also mirrored here:</p>
<ul>
<li>
<p><a href="/misc/archive/torrents/nfscars.net.2020.zip.torrent">2020 crawl</a></p>
</li>
<li>
<p><a href="/misc/archive/torrents/nfscars.net.2021.zip.torrent">2021 crawl</a></p>
</li>
</ul>
<p>Pieces of history get lost all the time with sites going offline. I&rsquo;m hoping that at least with this effort I have
managed
to do my part in preserving a tiny piece of it.</p>
<h2 id="2021-03-15-update">
  <a class="heading-anchor" href="#2021-03-15-update">2021-03-15 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The site seems to be down at the moment and has been for a couple of days. Oh no.</p>
<h2 id="2021-03-20-update">
  <a class="heading-anchor" href="#2021-03-20-update">2021-03-20 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Somehow the site is alive again.</p>
<h2 id="2024-08-20-update">
  <a class="heading-anchor" href="#2024-08-20-update">2024-08-20 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s dead.</p>
<p>However, I&rsquo;m delighted
to <a href="https://www.reddit.com/r/needforspeed/comments/1dc6bva/comment/l9otz0z/">find people using this archive to get their favourite mods!</a></p>
<p><a href="https://www.nfsaddons.com/forums/index.php?topic=2672.msg41002#msg41002">This post includes a guide on how to match up your favourite mod with the correct filename in my archive.</a>
I do wish that I had more time to properly organize that archive while creating it&hellip;</p>
<h2 id="2025-06-10-update">
  <a class="heading-anchor" href="#2025-06-10-update">2025-06-10 update<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I learned that there exists a browsable mirror of the nfscars.net
archive! <a href="https://www.nfs-cars.com/">You can find it on nfs-cars.com.</a>
I&rsquo;m very happy that it exists.</p>
]]></content:encoded></item><item><title>Things I've learned during my self-hosting adventure</title><link>https://ounapuu.ee/posts/2021/02/08/things-learned-while-self-hosting/</link><pubDate>Mon, 08 Feb 2021 16:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/02/08/things-learned-while-self-hosting/</guid><description>$HOME wasn't built in a day.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Things I've learned during my self-hosting adventure" /><p>This is a list of lessons that I&rsquo;ve learned while playing around with my computer setup during the last 6-7 years or so.</p>
<ul>
<li>USB connected storage is a bad idea when you are using BTRFS.</li>
<li>USB connected storage is still a bad idea when you are using ZFS, but it is at least much more resilient.</li>
<li>USB drive enclosures are a total crapshoot when it comes to the quality. Some are good, some will have random issues.</li>
<li><a href="https://en.wikipedia.org/wiki/Shingled_magnetic_recording">SMR</a> based hard drives can be <strong>unusably</strong> slow for
certain workloads.</li>
<li>Desktop PC-s use quite a lot of power when sitting mostly idle (50+ watts).</li>
<li>You might be OK with Intel QuickSync for your transcoding needs, try it out before opting for a much more powerful
hardware configuration.</li>
<li>Some hard drives are very, very loud. If you live in an apartment, keep this in mind, otherwise you will start trying
to rationalise the purchase of 8TB SSD-s to make your setup quieter.</li>
<li>ZFS snapshotting with a tool like <a href="https://github.com/jimsalterjrs/sanoid">Sanoid</a> is invaluable.</li>
<li>You will need to use your offline backups, don&rsquo;t think that you can get away without having some.</li>
<li>Five nines uptime is perfectly doable in a homelab environment, if you are willing to move the decimal point.</li>
<li>It&rsquo;s all fun and games until you have actual people using services on your server.</li>
<li>Who needs a fancy monitoring setup when you have your friends and family members yelling that the server is down?</li>
<li>VM-s are great for service isolation, but terrible for flexibility and efficiency.</li>
<li>Containers, if kept up to date, are an amazing way to manage your numerous services.</li>
<li>BTRFS is one of the few filesystem options on 32-bit ARM CPU based machines that can still provide data integrity
benefits.</li>
<li>Some workloads, such as databases and services with lots of random I/O, require an SSD to perform well.</li>
<li>If your workload is very heavily dependent on random I/O, then the &ldquo;pro&rdquo; branded SSD-s are actually worth the money.</li>
<li>SSD power usages can vary wildly, some may require 5V@1A, some up to <a href="mailto:5V@1.8A">5V@1.8A</a>. This will be problematic for hosts that
cannot supply much power through the USB ports, such as a Raspberry Pi.</li>
<li><a href="https://www.armbian.com/">Armbian</a> is great for SBC-s that support it.</li>
<li>Try running your database on a slow machine first. Any optimizations you will make will be very noticeable and your
database will fly once you move it to a more powerful machine.</li>
<li>Old laptops are a great way to start your self-hosting adventure, especially if you can limit the fan noise with a
tool like <code>thinkfan</code>.</li>
<li>External hard drives, such as the WD Elements or WD MyBook, are a great way to build multi-terabyte storage setups
without breaking the bank.</li>
<li>Raspberry Pi 4 specs sound good on paper, but its limited I/O capabilities prevent it from doing too many things at
once.</li>
<li>When setting up your system, document every command and installed package for future reference. You never know when it
may come in handy.</li>
<li>Configure your setup for <em><strong>when</strong></em> you get hacked.</li>
<li>Things will break at the most inconvenient time.</li>
<li>Some computers can be very temperamental. However, it might be easier to handle the quirks of one system rather than
getting a replacement and learning about its quirks the hard way.</li>
<li>Some workloads, such as <a href="https://github.com/internetarchive/heritrix3">Heritrix</a>, might not run well on all platforms,
such as arm64 or armhf.</li>
<li>The original Raspberry Pi 1 B+ is just too slow for most useful workloads in 2021, even when overclocked.</li>
<li>Having a filesystem that can protect from data corruption is a must-have.</li>
<li>Only use ZFS SLOG and L2ARC devices if you are absolutely sure that your workloads will benefit from them. If your
current ZFS ARC cache hit rate is already over 90+%, then it probably is not worth it.</li>
<li><a href="https://www.netdata.cloud/">Netdata</a> is both beautiful <em><strong>and</strong></em> useful.</li>
<li><a href="https://www.phoronix.com/scan.php?page=news_item&amp;px=CentOS-8-Ending-For-Stream">OS support cycles mean nothing and can be changed on a whim.</a></li>
<li>If you want a stable ZFS setup, use a distro that has a stable kernel version. Debian and Ubuntu are great for this
purpose.</li>
<li>Update and restart as often as possible. It&rsquo;s much easier to rule out what broke your setup if the amount of changes
that have built up is small.</li>
<li>Automate the way you deploy configuration changes to your server.</li>
</ul>
]]></content:encoded></item><item><title>How to fix ZFS pool not importing at boot</title><link>https://ounapuu.ee/posts/2021/02/01/how-to-fix-zfs-pool-not-importing-at-boot/</link><pubDate>Mon, 01 Feb 2021 08:45:27 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2021/02/01/how-to-fix-zfs-pool-not-importing-at-boot/</guid><description>You have probably tried Stack Exchange and reddit at this point, so what do you have to lose?</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="How to fix ZFS pool not importing at boot" /><h2 id="issue-description">
  <a class="heading-anchor" href="#issue-description">Issue description<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>You are running a Linux-based machine with an install of ZFS on Linux. Everything seems to work correctly, but
after restarting your machine, the ZFS pool is not visible. You can still import your pool manually using
<code>zpool import poolname</code> or <code>zpool import -a</code>.</p>
<p>In my situation, this issue does not occur with Debian 10 on an x86-based machine, but it does occur on a Raspberry Pi 4
running Ubuntu Server 20.04.1 LTS.</p>
<p>Setup:</p>
<ul>
<li>Raspberry Pi 4 (4GB)</li>
<li>Ubuntu Server 20.04.1</li>
<li>32GB microSD card for root filesystem</li>
<li>2x 8TB WD Elements external USB 3.0 drives (ZFS mirror)</li>
</ul>
<h2 id="potential-causes-and-solutions">
  <a class="heading-anchor" href="#potential-causes-and-solutions">Potential causes and solutions<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>When looking this issue up, there were many potential causes and solutions provided:</p>
<ul>
<li><a href="https://unix.stackexchange.com/a/338522">ensure that all ZFS related services are enabled</a></li>
<li><a href="https://serverfault.com/a/915191">add a startup delay in ZFS related configuration files</a></li>
<li><a href="https://serverfault.com/a/915191">just import the pools (duh)</a></li>
<li><a href="https://www.reddit.com/r/zfs/comments/9j714p/ubuntu_1804_zpool_mount_on_boot_does_not_work/e6p6zu0/">recreate the ZFS cache file</a></li>
</ul>
<p>In my specific scenario, none of these seemed to do the trick.</p>
<h2 id="investigation">
  <a class="heading-anchor" href="#investigation">Investigation<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The ZFS pools should be automatically imported on boot by a service named <code>zfs-import-cache.service</code>. The cache file
should contain information about the imported pools.</p>
<p>Once you have started your system and don&rsquo;t see any ZFS pools available, try running <code>systemctl status zfs-import-cache.service</code>
or <code>journalctl -u zfs-import-cache.service</code>. This should show you if the automatic import succeeded or not.</p>









<figure class="center">
  <a href="/posts/2021/02/01/how-to-fix-zfs-pool-not-importing-at-boot/media/zpool-import-fail.png">
    <img src="/posts/2021/02/01/how-to-fix-zfs-pool-not-importing-at-boot/media/zpool-import-fail_hu_b0e51bb16973b5be.webp"
     width="963"
     height="285"
     loading="lazy"
     decoding="async"
     alt="In my case, the failure shows up like this.">

  </a>
  <figcaption class="center">In my case, the failure shows up like this.</figcaption>
</figure>

<p>The pool <code>tanker</code> is a ZFS mirror that is supported by two 8TB WD Elements external hard drives. They are big, loud and
require some time to spin up the platters before you can actually read data off of them. At this point in the investigation,
a good friend recommended that I check what disks were recognized by the system at the time when this import service was
starting up.</p>
<p>For that, you need to modify the systemd service by running <code>systemctl edit zfs-import-cache.service</code> and put these contents
in there:</p>
<pre tabindex="0"><code>[Service]
ExecStartPre=/usr/bin/lsblk
</code></pre><p>This addition will run the <code>lsblk</code> command before the command specified in the systemd service is actually executed.
The output of this command will be visible in the service logs. After making this addition, reboot your system and run
<code>journalctl -u zfs-import-cache.service</code> again. You should be able to see all the connected drives on the system.</p>
<p>In my case, the system recognized the microSD card and an SSD that was connected over USB, but not the hard drives. This
was a very clear indication that the system was not waiting until the drives had spun up before attempting to import the
ZFS pool.</p>
<h2 id="hacky-solution">
  <a class="heading-anchor" href="#hacky-solution">Hacky solution<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>To resolve this issue quickly and move on with more interesting things, you can use the same trick that we used for
troubleshooting this issue, but instead of listing the connected hard drives, we can make the systemd service delay its
execution by putting a <code>sleep</code> statement in there.</p>
<p>Edit the systemd service again with <code>systemctl edit zfs-import-cache.service</code> and replace the contents with this:</p>
<pre tabindex="0"><code>[Service]
ExecStartPre=/usr/bin/sleep 15
</code></pre><p>This will make the service sleep for 15 seconds before importing the ZFS pool(s). It could be 10, or 30, or whatever value
works for you, 15 seconds was chosen here because it is more than enough time for the disks to spin up.</p>
<h2 id="proper-solution-probably">
  <a class="heading-anchor" href="#proper-solution-probably">Proper solution (probably)<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>There are probably better solutions, such as messing around with udev rules or enforcing the delay somewhere else in the
ZFS pool import chain of operations, but I have not investigated them at this point. Feel free to contact me with a better
solution, and I will update the post accordingly.</p>
]]></content:encoded></item><item><title>What running out of SATA ports looks like</title><link>https://ounapuu.ee/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/</link><pubDate>Sat, 29 Aug 2020 17:21:21 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/</guid><description>How I slapped two hard drives on a long PCIe x1 card.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="What running out of SATA ports looks like" /><p>One day I stumbled upon a <a href="https://www.youtube.com/watch?v=nQiWP8T9R60">Craft Computing video</a>
about his new server build, and on the parts list was a Sedna PCI Express 2x SATA adapter card:</p>









<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/image1.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/image1_hu_ab7a146edba408d5.webp"
     width="500"
     height="500"
     loading="lazy"
     decoding="async"
     alt="The card in question.">

  </a>
  <figcaption class="center">The card in question.</figcaption>
</figure>

<p>There are different designs out there, including a 4x SATA card, which is bonkers.</p>
<p>Anyway, I thought that I might as well give this a shot, since I have two 4TB 2.5&quot; 15mm Seagate hard drives running,
<a href="/posts/2020/08/22/disk-is-ok/">with one of them being in the process of accumulating bad sectors</a>.</p>









<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-48-37-1942.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-48-37-1942_hu_75dac604464ff51f.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="Adapter card with two drives installed (front).">

  </a>
  <figcaption class="center">Adapter card with two drives installed (front).</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-48-58-1944.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-48-58-1944_hu_2c16666f075f2054.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="Adapter card with two drives installed (back).">

  </a>
  <figcaption class="center">Adapter card with two drives installed (back).</figcaption>
</figure>

<p>The installation procedure itself is simple, just take your drives, screw them in and
plug this into a PCIe slot.</p>









<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-14-1945.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-14-1945_hu_158a5b5bf4dc792f.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="This is what it looks like installed into my server.">

  </a>
  <figcaption class="center">This is what it looks like installed into my server.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-19-1946.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-19-1946_hu_f6c7d8eb46ed23c0.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="Alternate angle.">

  </a>
  <figcaption class="center">Alternate angle.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-30-1947.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-19-55-30-1947_hu_d034eeb1ca74dcc6.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="Alternate angle.">

  </a>
  <figcaption class="center">Alternate angle.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-21-15-02-1948.jpg">
    <img src="/posts/2020/08/29/what-running-out-of-sata-ports-looks-like/media/20-08-26-21-15-02-1948_hu_8e6fd98d676b1c98.webp"
     width="1024"
     height="768"
     loading="lazy"
     decoding="async"
     alt="As you can see, it did not kill the system.">

  </a>
  <figcaption class="center">As you can see, it did not kill the system.</figcaption>
</figure>

<h2 id="so-how-well-does-it-work">
  <a class="heading-anchor" href="#so-how-well-does-it-work">So, how well does it work?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Quite well, actually.</p>
<p>The PCIe 2.0 x1 link does mean that your speeds will be capped at around 500MB/s, but
with current hard drives you are unlikely to reach this limit. SSD-s, on the other hand,
will be bottlenecked in sequential read/write workloads.</p>
<p><code>lspci -nnk</code> output:</p>
<pre tabindex="0"><code>01:00.0 SATA controller [0106]: ASMedia Technology Inc. ASM1062 Serial ATA Controller [1b21:0612] (rev 01)
        Subsystem: ASMedia Technology Inc. Device [1b21:1060]
        Kernel driver in use: ahci
        Kernel modules: ahci
</code></pre><p>The drives are individually addressable and show up as normal drives (like <code>/dev/sda</code>).
S.M.A.R.T info is functional and readable.</p>
<p>This adapter has been running in my system for over half a week now and so far
there haven&rsquo;t been any stability issues whatsoever.</p>
<h2 id="should-i-get-this">
  <a class="heading-anchor" href="#should-i-get-this">Should I get this?<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>This adapter is a good fit for the following use cases:</p>
<ul>
<li>there are no more HDD/SSD drive mounts in your system left and you do not want
to use double-sided tape as one</li>
<li>you have run out of SATA ports and don&rsquo;t mind using up a PCIe slot</li>
<li>you want to install additional SATA drives in your system, but also would prefer
to keep the amount of cabling in your system at a minimum</li>
<li>flexing on your friends with your fancy new 8/10 TB storage card</li>
</ul>
<p>I would recommend looking into alternative solutions if your use case matches one of these:</p>
<ul>
<li>using this adapter with SSD-s on sequential read/write workloads that exceed 500+MB/s</li>
<li>adding more than two SATA drives into your system (get a simple PCIe -&gt; SATA adapter
that only provides the data connectors instead)</li>
</ul>
]]></content:encoded></item><item><title>Stupid project ideas: the War Machine</title><link>https://ounapuu.ee/posts/2020/08/22/stupid-project-ideas-1/</link><pubDate>Sat, 22 Aug 2020 21:24:08 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2020/08/22/stupid-project-ideas-1/</guid><description>Maybe not stupid, but definitely stupid expensive.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Stupid project ideas: the War Machine" /><p><a href="https://www.youtube.com/user/LinusTechTips">LinusTechTips</a> has some pretty great videos about building
insane PC and server setups, such as:</p>
<ul>
<li>
<p><a href="https://youtu.be/EtZXMj_gUjU">unboxing and deploying <em>petabytes</em> of storage</a></p>
</li>
<li>
<p><a href="https://youtu.be/LXOaCkbt4lI">7 gamers, 1 CPU</a></p>
</li>
<li>
<p><a href="https://youtu.be/R_h63IsmvSQ">building sleeper PC-s</a></p>
</li>
<li>
<p><a href="https://youtu.be/uWtU8pGspj0">testing sketchy CPU-s</a></p>
</li>
<li>
<p><a href="https://youtu.be/ZFLiKClKKhs">opening up a 100TB SSD</a></p>
</li>
</ul>
<p>I have the ideas, but not the budget of LinusTechTips, so writing them down and hoping that one day I can test this out
is the best I can do for now.</p>
<h2 id="the-project-itself">
  <a class="heading-anchor" href="#the-project-itself">The project itself<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>The main idea is to have a laptop that has ridiculous amounts of storage and the performance to back it up.
The idea started gaining traction in my head after I realized that my Lenovo ThinkPad T430 can house up to 3 SSD-s, which
makes it a perfect candidate for a system with a ZFS mirror configuration. It also helps that it is powered by a quad-core
CPU and 16GB of RAM.</p>
<p>Additional points:</p>
<ul>
<li>low power, should stay below 60-90W even under the worst case scenarios</li>
<li>portable, just plug in the power and an ethernet cable and you are good to go</li>
<li>built-in UPS in the form of the laptop battery</li>
<li>well built, can survive a fall or two (already has done so, but that&rsquo;s a story for another time)</li>
<li>includes a screen and a keyboard for those times where you really screwed something up and need to fix it fast</li>
<li>supports 1x mSATA SSD (great for / partition) and 2x SATA HDD/SSD (one in the usual drive bay, the other in the HDD caddy that
is replacing the optical drive)</li>
</ul>
<h2 id="storage">
  <a class="heading-anchor" href="#storage">Storage<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With SSD prices having dropped quite low and capacities increasing with time, it might not be completely unreasonable
to get SSD-s with capacities reaching multiple terabytes. At the time of writing, Samsung, for example, is shipping
<a href="https://www.samsung.com/au/memory-storage/870-qvo-sata-3-2-5-ssd/MZ-77Q1T0BW/">SATA SSD-s with capacities up to 8TB</a>,
which is the same size as the main hard drives in my server right now.</p>
<p>However, these SSD-s are also ridiculously expensive, with the 4 TB model costing ~400 euros and the 8 TB costing almost
800 euros.</p>









<figure class="center">
  <a href="/posts/2020/08/22/stupid-project-ideas-1/media/2020-08-22-21-49-00.png">
    <img src="/posts/2020/08/22/stupid-project-ideas-1/media/2020-08-22-21-49-00_hu_ad198e1e6aaf23cd.webp"
     width="731"
     height="509"
     loading="lazy"
     decoding="async"
     alt="The capacity isn&#39;t the only thing that is big about this SSD.">

  </a>
  <figcaption class="center">The capacity isn&#39;t the only thing that is big about this SSD.</figcaption>
</figure>

<p>Hard drives are generally cheaper per TB, but in this case we don&rsquo;t actually have much better options. 2.5&quot; 9mm hard drives
seem to go up to 2TB at most. You will also have to take into account the fact that hard drives do not like impacts,
such as falls, and they are much slower than SSD-s in most workloads.</p>
<h2 id="cooling">
  <a class="heading-anchor" href="#cooling">Cooling<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>Since I have fitted this T430 with an <a href="https://ark.intel.com/content/www/us/en/ark/products/64889/intel-core-i7-3820qm-processor-8m-cache-up-to-3-70-ghz.html">Intel i7 3820QM</a>
CPU with a 45 watt TDP, cooling is an issue. Liquid metal, beefier heatsinks, fresh thermal paste, I have tried it all, but
the only solution that has actually worked is disabling the turbo boost feature. There is also this other solution I created
that automatically throttles the CPU at a chosen temperature limit using Intel p-state driver, but that solution requires
a rewrite.</p>
<p>With poor cooling comes great noise, so ideally this server should run in a place that does not bother anyone with its
high-pitched fan noise.</p>
<h2 id="performance">
  <a class="heading-anchor" href="#performance">Performance<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>With a quad core CPU, this system can do quite a lot. Running Nextcloud, PostgreSQL, Jellyfin or any other service should
be a breeze, especially since the main storage is SSD based. The amount of RAM is also perfectly suitable for doing quite
a lot. Run a couple of VM-s, transcode your media, it can do it all (with reasonable expectations, though).</p>
<h2 id="portability">
  <a class="heading-anchor" href="#portability">Portability<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>One of the best features of this setup is that you can just grab it and go, should the need arise. Its low power requirement
makes it a much more suitable candidate for powering it in situations where the electrical grid is down and all you have
is a generator or some form of renewable energy. In addition to that, everything you need to work with the machine is already
there, just open up the laptop and start working using the built-in keyboard and screen.</p>
<p>The good build quality of the laptop also means that you do not need to worry much about putting it in your backpack and
throwing it around. Sure, the plastic might break in some places, and if the impact is strong enough then it can still
break, but it is less likely to break when compared to alternative <em>thin and light</em> types of laptops.</p>
<h2 id="practicality">
  <a class="heading-anchor" href="#practicality">Practicality<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>It&rsquo;s not all fun and games, though. This setup does have quite a few downsides:</p>
<ul>
<li>no way to upgrade CPU and RAM any further. What you have is what you will have to live with.</li>
<li>it&rsquo;s expensive simply due to the fact that the SSD-s get very pricy if you require high capacities, hard drives
are still more economical for storing huge amounts of data</li>
<li>the cooling issue will remain unsolveable, unless you invest time and resources into designing a custom solution</li>
</ul>
<h2 id="conclusion">
  <a class="heading-anchor" href="#conclusion">Conclusion<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p><em>Do I still want to build this?</em></p>
<p>Yes.</p>
<p><em>Can I build this?</em></p>
<p>Not unless a delivery truck full of 8TB SSD-s happens to crash in front of me.</p>
<p>Or someone sponsors me. <em>Take a hint, WD/Seagate</em>.</p>
]]></content:encoded></item><item><title>Disk is OK</title><link>https://ounapuu.ee/posts/2020/08/22/disk-is-ok/</link><pubDate>Sat, 22 Aug 2020 07:29:19 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2020/08/22/disk-is-ok/</guid><description>It's all good, man.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Disk is OK" /><p>Maybe I am unlucky with computer hardware.</p>
<p>Maybe I have the opposite of <a href="https://en.wikipedia.org/wiki/Midas#Golden_Touch">the golden touch of Midas</a>.</p>
<p>Or maybe it&rsquo;s just the fact that I use my hardware for things they were never meant to be used for.</p>
<p>Anyway, I have acquired two Seagate 4TB external hard drives for doing some testing with ZFS.
I shucked them (took them out of their enclosure) and started using them as internal drives in many different
configurations.</p>
<p>Funnily enough, even though the two external drives had different branding (Backup Plus, Expansion)
and enclosure design, the hard drives in them were identical.</p>
<p>Some info about the drives:</p>
<ul>
<li>Model: ST4000LM024-2AN17V</li>
<li>Recording type: <a href="https://en.wikipedia.org/wiki/Shingled_magnetic_recording">SMR (shingled magnetic recording)</a></li>
<li>Form factor: 2.5&quot;</li>
<li>Interface: SATA</li>
<li>Thickness: <strong>15 mm</strong></li>
</ul>
<p>Before I get to the stupid stuff, I would like to mention what these drives are good for, and where they suffer heavily.</p>
<p>Good:</p>
<ul>
<li>WORM (write once, read many) type of workloads, such as a Steam library, your media collection etc.</li>
</ul>
<p>Bad:</p>
<ul>
<li>random read/write workloads (performance is absolutely rubbish and makes the system unusable)</li>
<li>write heavy workloads (SMR requires some clean-up activities that are managed by the drive, and you cannot do anything while
those take place)</li>
</ul>
<h2 id="the-stupid-stuff">
  <a class="heading-anchor" href="#the-stupid-stuff">The stupid stuff<svg class="heading-anchor__icon" viewBox="0 0 24 24" width="0.75em" height="0.75em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></a>
</h2>
<p>I have done some pretty dumb things with these, such as using them in an <a href="https://www.in-win.com/en/gaming-chassis/Chopin">InWin Chopin computer case</a>
and letting them hit 60C under load. Fun fact: these drives actually fit almost perfectly in the case, as long as you
bend one small metal section for one of the drive cages. Not so fun fact: they will overheat if you have a high CPU load
and you cannot do much about that.</p>
<p>Currently these drives are sitting in my main desktop. Initially I tried using them in a mirrored configuration under
Windows, because having your whole Steam library downloaded with disk space to spare is pretty cool. Unfortunately, one
of the disks started having issues and it got kicked out of the mirror. It kept doing this every time it accumulated bad
sectors.</p>
<p>Now these two sit in a ZFS mirror configuration inside a VM, acting as some sort of a temporary scratch disk. Another
free fun fact: <code>kvm</code> (or qemu, or libvirt, one of those) will pause the VM if it detects that one of your disks has
encountered I/O errors, and seems that the only &ldquo;fix&rdquo; is to force a restart of the VM (could not unpause the VM).</p>
<p>It has become some sort of a fun pastime for me to keep an eye on one of the failing drives and the status of the ZFS mirror.</p>
<p><em>Will ZFS detect some errors?</em></p>
<p><em>How large can the bad sector count get before the drive dies?</em></p>
<p><em>When will it actually die?</em></p>
<p><em>Why is <a href="https://en.wikipedia.org/wiki/S.M.A.R.T.">S.M.A.R.T</a> <em>still</em> reporting that the disk is OK?</em></p>
<p>So far, so good.</p>









<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-08-17-07-45-51.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-08-17-07-45-51_hu_5c5bafe4f031a67.webp"
     width="414"
     height="151"
     loading="lazy"
     decoding="async"
     alt="2020-08-17. Nope, not OK.">

  </a>
  <figcaption class="center">2020-08-17. Nope, not OK.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-08-20-23-21-28.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-08-20-23-21-28_hu_cb45e12ea3173227.webp"
     width="425"
     height="157"
     loading="lazy"
     decoding="async"
     alt="2020-08-20. Still not OK.">

  </a>
  <figcaption class="center">2020-08-20. Still not OK.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-08-22-20-49-21.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-08-22-20-49-21_hu_e8727e34f879c63c.webp"
     width="423"
     height="153"
     loading="lazy"
     decoding="async"
     alt="2020-08-22. OK, that&#39;s pretty bad.">

  </a>
  <figcaption class="center">2020-08-22. OK, that&#39;s pretty bad.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-08-29-17-10-38.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-08-29-17-10-38_hu_aae832d18d06b1cf.webp"
     width="837"
     height="173"
     loading="lazy"
     decoding="async"
     alt="2020-08-29. Moved this to a proper server box.">

  </a>
  <figcaption class="center">2020-08-29. Moved this to a proper server box.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-09-11-07-44-31.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-09-11-07-44-31_hu_7efd2b0d2b5e7cf6.webp"
     width="1174"
     height="397"
     loading="lazy"
     decoding="async"
     alt="2020-09-09. He&#39;s dead, Jim.">

  </a>
  <figcaption class="center">2020-09-09. He&#39;s dead, Jim.</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-09-12-11-49-21.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-09-12-11-49-21_hu_388360a48b055b14.webp"
     width="835"
     height="182"
     loading="lazy"
     decoding="async"
     alt="2020-09-12. One restart later: it&#39;s back!">

  </a>
  <figcaption class="center">2020-09-12. One restart later: it&#39;s back!</figcaption>
</figure>










<figure class="center">
  <a href="/posts/2020/08/22/disk-is-ok/media/2020-09-22-08-22-22.png">
    <img src="/posts/2020/08/22/disk-is-ok/media/2020-09-22-08-22-22_hu_6075a8592b11b062.webp"
     width="836"
     height="169"
     loading="lazy"
     decoding="async"
     alt="2020-09-22. More errors, more work for ZFS.">

  </a>
  <figcaption class="center">2020-09-22. More errors, more work for ZFS.</figcaption>
</figure>

<p>Expect this list to grow with time.</p>
]]></content:encoded></item></channel></rss>