<?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/tags/backup/</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, 15 Jan 2025 06:00:00 +0200</lastBuildDate><atom:link href="https://ounapuu.ee/tags/backup/index.xml" rel="self" type="application/rss+xml"/><item><title>Backing up another PC with a single Ethernet cable</title><link>https://ounapuu.ee/posts/2025/01/15/backups-without-disk/</link><pubDate>Wed, 15 Jan 2025 06:00:00 +0200</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2025/01/15/backups-without-disk/</guid><description>If all you have is an Ethernet cable, then everything looks like a temporary storage device.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/posts/2025/01/15/backups-without-disk/media/cover_hu_9014625e7ebdbb4.jpg" width="1200" height="630" alt="Backing up another PC with a single Ethernet cable" /><p>I was in a pinch.</p>
<p>I needed to make a full disk backup of a PC, but I had no external storage device with me to store it on.
The local Wi-Fi network was also way too slow to transfer the disk over it.</p>
<p>All I had was my laptop with an Ethernet port, a Fedora Linux USB stick, and a short Ethernet cable.</p>
<p>I took the following steps:</p>
<ul>
<li>boot the target machine up with the Fedora Linux installer in a live environment</li>
<li>modify the SSH configuration on the target machine to allow <code>root</code> user login with a password
<ul>
<li>it&rsquo;s OK to do this on a temporary setup like this one, but don&rsquo;t do it on an actual Linux server</li>
</ul>
</li>
<li>set a password for the <code>root</code> user on the target machine
<ul>
<li>only required because a live environment usually does not set one for <code>root</code> user</li>
</ul>
</li>
<li>connect both laptops with the Ethernet cable</li>
<li>set static IPv4 addresses on both machines using network settings <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
<ul>
<li>edit the &ldquo;Wired&rdquo; connection and open the IPv4 tab</li>
<li>example IP address on target: 192.168.100.5</li>
<li>example IP address on my laptop: 192.168.100.1</li>
<li>make sure to set the netmask to 255.255.255.0 on both!</li>
</ul>
</li>
<li>verify that the SSH connection works to the target machine</li>
<li>back up the disk to your local machine using <code>ssh</code> and <code>dd</code>
<ul>
<li>example: <code>ssh root@192.168.100.5 &quot;dd if=/dev/sda&quot; | dd of=disk-image-backup.iso status=progress</code></li>
<li>replace <code>/dev/sda</code> with the correct drive name!</li>
</ul>
</li>
</ul>
<p>And just like that, I backed up the 120 GB SSD at gigabit speeds to my laptop.</p>









<figure class="center">
  <a href="/posts/2025/01/15/backups-without-disk/media/setup-0.jpg">
    <img src="/posts/2025/01/15/backups-without-disk/media/setup-0_hu_9fc5ce3a493235ab.webp"
     width="1000"
     height="750"
     loading="lazy"
     decoding="async"
     alt="Copying in progress.">

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










<figure class="center">
  <a href="/posts/2025/01/15/backups-without-disk/media/setup-1.jpg">
    <img src="/posts/2025/01/15/backups-without-disk/media/setup-1_hu_5f8d76c41d88289b.webp"
     width="1000"
     height="750"
     loading="lazy"
     decoding="async"
     alt="It might be only 105 MB/s, but it beat doing the same over Wi-Fi at 1.5 MB/s!">

  </a>
  <figcaption class="center">It might be only 105 MB/s, but it beat doing the same over Wi-Fi at 1.5 MB/s!</figcaption>
</figure>

<p>I&rsquo;ve used a similar approach in the past when switching between laptops by running a live environment on both machines
and copying the disk over with <code>dd</code> bit by bit.</p>
<p>You&rsquo;ll also save time on not having to copy the data over twice, first to an external storage device, and then to the
target device.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>there&rsquo;s probably a simpler way to do this with IPv6 magic, but I have not tested it yet&#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 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>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>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 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>Overcoming hardware limitations: the time-to-sleep script</title><link>https://ounapuu.ee/posts/2022/08/26/the-time-to-sleep-script/</link><pubDate>Fri, 26 Aug 2022 08:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/08/26/the-time-to-sleep-script/</guid><description>Sometimes the least technical solutions end up being the ones that I'm the most proud of. This is probably one of them.</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Overcoming hardware limitations: the time-to-sleep script" /><p>As some of you might own, <a href="/posts/2022/01/09/why-i-went-back-to-using-a-thinkpad-from-2012/">I&rsquo;m still rocking a ThinkPad T430, a laptop model
originally released in 2012.</a>
It&rsquo;s not the fastest laptop out there, but it is plenty fast for a number of
tasks, even most software development work.</p>
<p>I also try to keep my machines up to date and properly backed up. On my laptop,
this means having around a couple of scheduled tasks, such as <code>restic</code> backups.
They don&rsquo;t really take up a lot of time, but if an intensive scheduled task
starts while you&rsquo;re having a video call over Google Meet while also sharing
the screen, things can get a bit slow, ruining the experience.</p>
<p>After a couple of these instances, I started thinking about finding a solution.</p>
<h2 id="scheduled-tasks">
  <a class="heading-anchor" href="#scheduled-tasks">Scheduled tasks<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 regular tasks that I like to run on my laptop.</p>
<p><strong>Backups using <code>restic</code></strong>: hourly backups to my home server. The file scanning
process of the backup is quite intense, eating up a lot of my CPU time.</p>
<p><strong>System updates using <code>dnf</code> and <code>flatpak</code></strong>: usually run daily, because I&rsquo;m too
lazy to install the updates using a GUI, and at the same time I cannot afford
to run out of date software.</p>
<p><strong>Backups of critical files from my server to my laptop</strong>: there are some files
I just cannot afford to lose. For this reason, I make a daily backup of the
files to my laptop.</p>
<p><strong>Filesystem maintenance</strong>: I don&rsquo;t trust my storage devices (and neither should
you), which is why I run a weekly scrub on my SSD that&rsquo;s running the <code>btrfs</code>
filesystem. If there are errors detected, I will know as soon as possible.</p>
<p>These tasks can be quite intensive, especially on hardware that&rsquo;s a bit older.</p>
<p>With some tasks, such as system updates, you may also run into random
issues. Updating Mozilla Firefox while it&rsquo;s actively running results in the
browser requiring a restart immediately after opening a new tab. This is very
annoying and inconvenient when you&rsquo;re in the middle of your work.</p>
<h2 id="the-time-to-sleep-script">
  <a class="heading-anchor" href="#the-time-to-sleep-script">The &ldquo;time-to-sleep&rdquo; script<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 avoid intensive scheduled tasks running while I&rsquo;m doing actual work, I tried
rescheduling these tasks to a more quiet time. All I needed to do was to edit
the <code>systemd</code> timers so that the jobs start after midnight and leave the laptop
running.</p>
<p>This solution has quite an obvious downside: my laptop will be powered on
pretty much 24/7, and since electricity is super expensive and laptop
maintenance a bit of a pain, I&rsquo;d be wasting resources, time and eventually
money.</p>
<p>I <em>could</em> make the last scheduled task make the machine shut down, but what if I
have a long-running file copy operation running? It would be interrupted, unless
I specifically disabled the scheduled task.</p>
<p>Then it clicked for me.</p>
<p>I know when I&rsquo;m planning on going to sleep. Sleeping also has a regular cycle
as it happens daily. Why not just put all the scheduled daily tasks into one
script that I can run whenever I intend to shut down my laptop?</p>
<p>And thus, the <code>time-to-sleep</code> script was born. It&rsquo;s a simple Bash script that
lives in <code>/root/.local/bin/time-to-sleep</code>. To make sure I can also reasonably
observe the behaviour of the script, I&rsquo;ve implemented it as a simple <code>systemd</code>
service that lives in <code>/etc/systemd/system/time-to-sleep.service</code>. It&rsquo;s
disabled by default, but can be started manually.</p>
<pre tabindex="0"><code>[Unit]
Description=Run maintenance tasks

[Service]
ExecStart=/root/.local/bin/time-to-sleep
</code></pre><p>I have an alias in <code>~/.bashrc</code> that I use to start the service.</p>
<pre tabindex="0"><code>alias time-to-sleep=&#34;sudo systemctl start time-to-sleep.service&#34;
</code></pre><p>Whenever the time comes to go to sleep, or when I&rsquo;m just going to do something
else and can leave the laptop running at my desk, I just open a terminal window,
type <code>time-to-sleep</code> and I&rsquo;m good to go. If I&rsquo;m somewhere with a very poor
internet connection or need to conserve battery power, I can opt to not run that
script.</p>
<p>Going with this approach also saves me a lot of trouble on the technical side
as well. I don&rsquo;t need to think of a magical way to automatically detect if I&rsquo;m
working at the moment, or if I&rsquo;m running on battery, or if I&rsquo;m behind a limited
internet connection. Sometimes your job becomes so much easier if you make some
assumptions about when and where the script runs. You&rsquo;re in control of choosing
when to run it, after all.</p>
<p>In case something goes wrong, I can rely on the <code>set -e</code> line in my script to
fail hard. When I come back to my machine, it will be quite noticeable that
something has gone wrong, as the laptop will still be running. Who needs a
fancy monitoring setup when you have visual evidence of failure?</p>
<p>As for the hourly backups, I solved that problem by only making backups of
more important files. It takes much fewer resources compared to the full <code>/home</code>
folder backup that runs as part of the <code>time-to-sleep</code> script.</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>After all this work, I don&rsquo;t have to worry about any scheduled tasks hogging
up all the resources while working. At the same time, I still get all the
benefits that the scheduled tasks bring.</p>
<h2 id="example">
  <a class="heading-anchor" href="#example">Example<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>In case you need it: here&rsquo;s an example of the script that I&rsquo;m running, with all
the personal details scrubbed out. Feel free to use it as inspiration for your
own <code>time-to-sleep</code> script!</p>
<pre tabindex="0"><code>#!/bin/bash

set -e

echo &#34;Restic full home folder backup.&#34;
export RESTIC_REPOSITORY=&#39;sftp:backupuser@backupserver.lan:/path/to/repo/&#39;
export RESTIC_PASSWORD=&#39;someverysecurepasswordgoeshere&#39;

restic unlock

restic backup --verbose --exclude-caches --cleanup-cache \
  --iexclude=/home/*/downloads \
  --exclude=/home/*/.cache \
  --exclude=/home/*/.gradle \
  --exclude=/home/*/.local/share/Trash \
  /home

restic forget --prune \
  --keep-hourly 0 \
  --keep-daily 7 \
  --keep-monthly 0

echo &#34;Restic full home folder backup done.&#34;

echo &#34;Backing up important data from the server.&#34;

rsync -az --delete-before \
  user@myserver.lan:/path/to/nextcloud/ \
  /storage/backups/nextcloud/

chown -R localuser:localuser /storage/backups/nextcloud/

echo &#34;Backing up important data from the server done.&#34;

echo &#34;Updating system.&#34;

dnf update -y

flatpak update -y &amp;&amp; flatpak uninstall --unused -y

echo &#34;Updating system done.&#34;

echo &#34;Scrubbing disk.&#34;
btrfs scrub start -B /
echo &#34;Scrubbing disk done.&#34;

echo &#34;All done! Going to sleep.&#34;

shutdown now
</code></pre>]]></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>Oversimplified guide into snapshots on the btrfs filesystem</title><link>https://ounapuu.ee/posts/2022/04/05/btrfs-snapshots/</link><pubDate>Tue, 05 Apr 2022 06:00:00 +0300</pubDate><author>ihavesomethoughtsonyourblog@ounapuu.ee (Herman Õunapuu)</author><guid>https://ounapuu.ee/posts/2022/04/05/btrfs-snapshots/</guid><description>Oh, snap(per)!</description><content:encoded><![CDATA[<img src="https://ounapuu.ee/media/cover_hu_4fe4cf2661554252.jpg" width="1200" height="630" alt="Oversimplified guide into snapshots on the btrfs filesystem" /><p><em><strong>Update:</strong></em> I&rsquo;ve switched to <a href="/posts/2022/07/09/btrbk-is-awesome/">btrbk</a> for managing btrfs snapshots due to certain
deficiencies that I had with <code>snapper</code>. Those may have been fixed since then, but <code>btrbk</code> has served me very well, and
I&rsquo;m sticking with it in the foreseeable future.</p>
<p>Friday afternoon. You&rsquo;re trying out a script that you wrote to mass-rename and
move some files around. You finish the script and test it out.</p>
<p>Oops.</p>
<p>All the files now have all the wrong names, and some have been randomly moved
10 folders deep. It&rsquo;s a mess.</p>
<p>And you didn&rsquo;t make a backup of your files right before this step because
you thought that you wouldn&rsquo;t need it. <em>It&rsquo;s just a simple script, after all&hellip;</em></p>
<p>If you&rsquo;ve found yourself in a similar situation and want to know how to avoid
problems in the future, then this article is for you</p>
<h2 id="btrfs-overview">
  <a class="heading-anchor" href="#btrfs-overview">btrfs: 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>









<figure class="center">
  <a href="/posts/2022/04/05/btrfs-snapshots/media/btrfs.png" aria-label="View full-size image">
    <img src="/posts/2022/04/05/btrfs-snapshots/media/btrfs_hu_6d2804214375925e.webp"
     width="593"
     height="328"
     loading="lazy"
     decoding="async"
     alt="">

  </a>
  
</figure>

<p><a href="https://btrfs.wiki.kernel.org/index.php/Main_Page">btrfs</a>
(<em>butter-fs, bee-tee-arr-eff-ess</em>) is a modern filesystem present in the Linux
kernel that has a lot of great features:</p>
<ul>
<li>different RAID levels: RAID0, RAID1, RAID10&hellip;</li>
<li>data integrity guarantees</li>
<li>snapshots</li>
<li>and many more!</li>
</ul>
<p><code>btrfs</code> does have some downsides and has had its fair share of issues and
controversy in the past, but at least during the last couple of years it&rsquo;s been
fine in my simple RAID1 + snapshots use cases.</p>
<p>In this post, we&rsquo;ll focus on the snapshots feature that <code>btrfs</code> offers.</p>
<p>If you&rsquo;re not sure what snapshots are, then you can think of them as a still
image of the state of your filesystem at a certain point in time. You can create
a snapshot of the filesystem, delete all your files, and still be able to get
your files back just like you left them.</p>
<p>If you&rsquo;re a developer who has used <code>git</code> and doesn&rsquo;t mind oversimplified (and
probably incorrect) explanations: you can think of snapshots like <code>git</code> commits.
You can take snapshots (commit), roll back to a previous snapshot (reset/revert)
or view the contents of a previous snapshot (checkout commit).</p>
<p>One thing to keep in mind with snapshots is that they will take up space,
especially if you make a lot of them and move files around a lot.</p>
<p>There are many tools available to manage <code>btrfs</code> snapshots. The one I&rsquo;ve opted
for is <a href="http://snapper.io/">snapper</a>.</p>
<h2 id="snapper-quick-start">
  <a class="heading-anchor" href="#snapper-quick-start">Snapper quick-start<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 guide on how to get started with snapshotting your <code>btrfs</code>
filesystem. The example is based on a system with a <code>btrfs</code> filesystem mounted
on <code>/home</code></p>
<ul>
<li>Install <code>snapper</code>
<ul>
<li>Ubuntu/Debian: <code>sudo apt install snapper</code></li>
<li>Fedora: <code>sudo dnf install snapper</code></li>
</ul>
</li>
<li>Setup the configuration: <code>sudo snapper -c home create-config /home</code></li>
<li><code>/etc/snapper/configs</code> now has a text file named <code>home</code> that you can configure
to your liking. My personal recommendation is to use the <code>TIMELINE</code> snapshots
configuration to configure the maximum number of hourly and daily snapshots.</li>
<li><code>snapper</code> ships with two systemd timers that automatically take new snapshots
and remove old ones. Make sure that they are enabled:
<ul>
<li><code>sudo systemctl enable --now snapper-timeline.timer snapper-cleanup.timer</code></li>
</ul>
</li>
<li>After a while, you should be able to see snapshots appear in the output of
<code>sudo snapper -c home list</code>.</li>
<li>If you want to browse the files for the old snapshots, go to <code>/home/.snapshots</code>.</li>
</ul>
<p>Example output of <code>sudo snapper -c home  list</code> on my machine:</p>
<pre tabindex="0"><code>&gt; sudo snapper -c home list

    # | Type   | Pre # | Date                     | User | Cleanup  | Description | Userdata
------+--------+-------+--------------------------+------+----------+-------------+---------
   0  | single |       |                          | root |          | current     |         
   1  | single |       | K 16 märts 2022 08:12:01 | root | timeline |             |         
 242  | single |       | K 16 märts 2022 13:00:16 | root | timeline |             |         
 302  | single |       | K 16 märts 2022 14:00:05 | root | timeline |             |         
 362  | single |       | K 16 märts 2022 15:00:10 | root | timeline |             |         
 422  | single |       | K 16 märts 2022 16:00:19 | root | timeline |             |         
 461  | single |       | K 16 märts 2022 17:20:29 | root | timeline |             |         
 501  | single |       | K 16 märts 2022 18:00:02 | root | timeline |             |
...         
</code></pre><p>That&rsquo;s it!</p>
<h2 id="snapper-tech-tips">
  <a class="heading-anchor" href="#snapper-tech-tips">Snapper 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&rsquo;re new to snapshots, then I recommend keeping an eye on your disk usage
and tuning the <code>snapper</code> timeline related configurations to your liking. For my
<code>/home</code> folder, my configuration looks like this:</p>
<pre tabindex="0"><code># create hourly snapshots
TIMELINE_CREATE=&#34;yes&#34;

# cleanup hourly snapshots after some time
TIMELINE_CLEANUP=&#34;yes&#34;

# limits for timeline cleanup
TIMELINE_MIN_AGE=&#34;300&#34;
TIMELINE_LIMIT_HOURLY=&#34;48&#34;
TIMELINE_LIMIT_DAILY=&#34;7&#34;
TIMELINE_LIMIT_WEEKLY=&#34;0&#34;
TIMELINE_LIMIT_MONTHLY=&#34;0&#34;
TIMELINE_LIMIT_YEARLY=&#34;0&#34;
</code></pre><p>With this configuration, I can undo my screw-ups for up to 7 days, with more
granular control for changes done within the last 48 hours.</p>
<p>If you have data that changes more often than other data on the same filesystem,
then I recommend utilizing <code>btrfs</code> subvolumes and creating separate <code>snapper</code>
configurations for each.</p>
<p>For example: a folder containing gigabytes of cat pictures is unlikely to change
all that often, so a longer snapshot retention policy of 24 hourly/30 daily
snapshots is a sensible one.</p>
<p>However, the contents of my <code>downloads</code> folder changes more frequently and may
contain bigger files that I need temporarily, such as the ISO file for the
latest Fedora/Debian release. In a situation like that, having a 6 hourly/7
daily snapshots policy will make more sense, especially if I don&rsquo;t want to run
out of space due to excessive number of snapshots taken for that filesystem.</p>
<h2 id="further-reading-zfs-snapshots">
  <a class="heading-anchor" href="#further-reading-zfs-snapshots">Further reading: ZFS snapshots<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://zfsonlinux.org/">ZFS</a> is a fantastic filesystem that offers many of
the features boasted by <code>btrfs</code>, and some that <code>btrfs</code> doesn&rsquo;t have. ZFS also
supports snapshots. To set up automatic snapshot creation and pruning on ZFS,
I can recommend <a href="https://github.com/jimsalterjrs/sanoid">sanoid</a>.</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>