<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>debian &amp;mdash; Jerry of the Week</title>
    <link>https://write.in0rdr.ch/tag:debian</link>
    <description>ˈdʒɛri - Individual who sends life against the grain no matter the consequences</description>
    <pubDate>Tue, 28 Apr 2026 12:56:52 +0000</pubDate>
    <item>
      <title>Emulate Raspberry Pi4 on QEMU</title>
      <link>https://write.in0rdr.ch/emulate-raspberry-pi4-on-qemu</link>
      <description>&lt;![CDATA[I was looking into emulating the Raspberry Pi OS on QEMU. This short post summarizes my findings.&#xA;&#xA;#raspberry #homelab #debian #qemu&#xA;!--more--&#xA;&#xA;I needed a virtual host to test Ansible scripts for my Raspberry Pi in the home lab. I found my way around this task by reading through the many great posts and examples online.&#xA;&#xA;Extract kernel and device tree&#xA;&#xA;First, you have to get the image (in my case, I used a modified build of the bookworm image) and extract the &#34;kernel&#34; and the &#34;device tree&#34; (to be honest, this was new for me when I read about this today).&#xA;&#xA;We do this by mounting the boot partition and extracting the relevant files.&#xA;&#xA;Check image partitions&#xA;$ fdisk -l ./HashiPi-pi0.img&#xA;&#xA;Setup loop device with image, scan partitions. This is easier than fiddling with fdisk and partition offsets for mounting.&#xA;&#xA;$ sudo losetup -P /dev/loop0 HashiPi-pi0.img&#xA;$ sudo mount /dev/loop0p1 /mnt&#xA;&#xA;copy kernel and device tree binary (dtb)&#xA;$ cp /mnt/kernel8.img .&#xA;$ cp /mnt/bcm2711-rpi-4-b.dtb .&#xA;&#xA;unmount&#xA;$ sudo umount /mnt&#xA;$ sudo losetup --detach /dev/loop0&#xA;&#xA;Patch device tree to enable USB controller&#xA;&#xA;The &#34;device tree binary&#34; (.dtb) needs to be translated into a readable &#34;device tree source&#34; (.dts) file.&#xA;&#xA;$ dtc -I dtb -O dts -o bcm2711-rpi-4-b.dts bcm2711-rpi-4-b.dtb&#xA;&#xA;The .dts file can be patched to enable the usb controller. This is required, if we want to boot later using the usbnet device and port-forward (hostfwd) the ssh port.&#xA;&#xA;--- bcm2711-rpi-4-b.dts.orig    2025-09-21 15:05:59.304575294 +0200&#xA;+++ bcm2711-rpi-4-b.dts 2025-09-21 15:04:56.709581742 +0200&#xA;@@ -1450,7 +1450,7 @@&#xA;                        phy-names = &#34;usb2-phy&#34;;&#xA;                        interrupt-names = &#34;usb&#34;, &#34;soft&#34;;&#xA;                        power-domains = 0x10 0x06;&#xA;status = &#34;disabled&#34;;&#xA;status = &#34;okay&#34;;&#xA;                        phandle = 0xbf;&#xA;                };&#xA;&#xA;Unfortunately, we need to use this usb device, because all other emulated network devices are pci based which is not supported by QEMU for the Raspberry Pi&#xA;&#xA;$ qemu-system-aarch64 -device help&#xA;...&#xA;Network devices:&#xA;name &#34;e1000&#34;, bus PCI, alias &#34;e1000-82540em&#34;, desc &#34;Intel Gigabit Ethernet&#34;&#xA;name &#34;e1000-82544gc&#34;, bus PCI, desc &#34;Intel Gigabit Ethernet&#34;&#xA;name &#34;e1000-82545em&#34;, bus PCI, desc &#34;Intel Gigabit Ethernet&#34;&#xA;name &#34;e1000e&#34;, bus PCI, desc &#34;Intel 82574L GbE Controller&#34;&#xA;name &#34;i82550&#34;, bus PCI, desc &#34;Intel i82550 Ethernet&#34;&#xA;name &#34;i82551&#34;, bus PCI, desc &#34;Intel i82551 Ethernet&#34;&#xA;name &#34;i82557a&#34;, bus PCI, desc &#34;Intel i82557A Ethernet&#34;&#xA;name &#34;i82557b&#34;, bus PCI, desc &#34;Intel i82557B Ethernet&#34;&#xA;name &#34;i82557c&#34;, bus PCI, desc &#34;Intel i82557C Ethernet&#34;&#xA;name &#34;i82558a&#34;, bus PCI, desc &#34;Intel i82558A Ethernet&#34;&#xA;name &#34;i82558b&#34;, bus PCI, desc &#34;Intel i82558B Ethernet&#34;&#xA;name &#34;i82559a&#34;, bus PCI, desc &#34;Intel i82559A Ethernet&#34;&#xA;name &#34;i82559b&#34;, bus PCI, desc &#34;Intel i82559B Ethernet&#34;&#xA;name &#34;i82559c&#34;, bus PCI, desc &#34;Intel i82559C Ethernet&#34;&#xA;name &#34;i82559er&#34;, bus PCI, desc &#34;Intel i82559ER Ethernet&#34;&#xA;name &#34;i82562&#34;, bus PCI, desc &#34;Intel i82562 Ethernet&#34;&#xA;name &#34;i82801&#34;, bus PCI, desc &#34;Intel i82801 Ethernet&#34;&#xA;name &#34;igb&#34;, bus PCI, desc &#34;Intel 82576 Gigabit Ethernet Controller&#34;&#xA;name &#34;ne2kpci&#34;, bus PCI&#xA;name &#34;pcnet&#34;, bus PCI&#xA;name &#34;rocker&#34;, bus PCI, desc &#34;Rocker Switch&#34;&#xA;name &#34;rtl8139&#34;, bus PCI&#xA;name &#34;tulip&#34;, bus PCI&#xA;-  name &#34;usb-net&#34;, bus usb-bus&#xA;name &#34;virtio-net-device&#34;, bus virtio-bus # No &#39;virtio-bus&#39; bus found for device &#39;virtio-net-device&#39;&#xA;name &#34;virtio-net-pci&#34;, bus PCI, alias &#34;virtio-net&#34;&#xA;name &#34;virtio-net-pci-non-transitional&#34;, bus PCI&#xA;name &#34;virtio-net-pci-transitional&#34;, bus PCI&#xA;name &#34;vmxnet3&#34;, bus PCI, desc &#34;VMWare Paravirtualized Ethernet v3&#34;&#xA;&#xA;We really need the usb device (virtio-net-device does not work either I tried), that&#39;s the reason for the patch.&#xA;&#xA;A comment of the &#34;interrupt.memfault blog&#34; describes it nicely (very helpful community):&#xA;&#xA;  Note that for raspi4, the bcm2711-rpi-4-b.dtb devicetree file has disabled the USB controller.&#xA;So, to enable USB keyboard &amp; mouse, the .dtb file must be decompiled to .dts,&#xA;patched, and recompiled back to .dtb.&#xA;&#xA;Unfortunately, it&#39;s not only needed for keyboard and mouse, but also to make our network adapter work (for ssh port-forwarding).&#xA;&#xA;Thaa patching.. Then recompiling into binary form with dtc:&#xA;$ dtc -I dtb -O dts -o bcm2711-rpi-4-b.dts bcm2711-rpi-4-b.dtb&#xA;&#xA;Would be really nice to have this usb controller enabled by default in the next Trixie Pi OS 🤞&#xA;&#xA;Boot the image&#xA;&#xA;For booting the image, I had to ensure two things for the kernel arguments for the Raspberry 4:&#xA;&#xA;Use the ttyAMA1 console&#xA;Use the root partition mmcblk1p2&#xA;&#xA;Note that I&#39;m not enabling the keyboard &amp; mouse devices (as suggested in the references online), because I&#39;m mainly interested to connect to the machine remotely via the ssh port fowarding:&#xA;&#xA;$ sudo qemu-system-aarch64 \&#xA;  -machine raspi4b -cpu cortex-a72 \&#xA;  -dtb bcm2711-rpi-4-b-mod.dtb \ # use mod device tree&#xA;  -m 2G -smp 4 \&#xA;  -kernel kernel8.img -sd HashiPi-pi0.img \&#xA;  -append &#34;rw earlyprintk loglevel=8 console=ttyAMA1,115200 dwcotg.lpm_enable=0 root=/dev/mmcblk1p2 rootdelay=1&#34; \&#xA;  -device usb-net,netdev=net0 \&#xA;  -netdev user,id=net0,hostfwd=tcp::2222-:22&#xA;&#xA;That&#39;s it. Is still a bit slow, but good enough to throw some Ansible against the wall and see if it sticks.&#xA;&#xA;My idea here is to do less with the HashiCorp packer scripts and go back to more Ansible, because that might be more sustainable in the long run.. Let&#39;s see. Next I&#39;m probably also going to give the Trixie (nightly image) a try.&#xA;&#xA;References&#xA;&#xA;https://interrupt.memfault.com/blog/emulating-raspberry-pi-in-qemu&#xA;https://www.qemu.org/docs/master/system/qemu-manpage.html&#xA;https://www.qemu.org/docs/master/system/arm/raspi.html&#xA;https://github.com/trinitronx/qemu-raspbian/blob/main/run-raspi4.sh&#xA;https://github.com/trinitronx/qemu-raspbian/blob/main/bcm2711-rpi-4-b.dts.patch&#xA;https://downloads.raspberrypi.org&#xA;https://www.man7.org/linux/man-pages/man8/losetup.8.html&#xA;&#xA;div style=&#34;text-align:center; font-size: 0.8em&#34;&#xD;&#xA;a href=&#34;https://write.in0rdr.ch/feed&#34;&amp;#128732; RSS/a | a href=&#34;https://m.in0rdr.ch/in0rdr&#34;&amp;#128024; Fediverse/a | a href=&#34;https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch&#34;&amp;#128172; XMPP/a&#xD;&#xA;/div]]&gt;</description>
      <content:encoded><![CDATA[<p>I was looking into emulating the Raspberry Pi OS on QEMU. This short post summarizes my findings.</p>

<p><a href="https://write.in0rdr.ch/tag:raspberry" class="hashtag"><span>#</span><span class="p-category">raspberry</span></a> <a href="https://write.in0rdr.ch/tag:homelab" class="hashtag"><span>#</span><span class="p-category">homelab</span></a> <a href="https://write.in0rdr.ch/tag:debian" class="hashtag"><span>#</span><span class="p-category">debian</span></a> <a href="https://write.in0rdr.ch/tag:qemu" class="hashtag"><span>#</span><span class="p-category">qemu</span></a>
</p>

<p>I needed a virtual host to test Ansible scripts for my Raspberry Pi in the home lab. I found my way around this task by reading through the many great posts and examples online.</p>

<h2 id="extract-kernel-and-device-tree">Extract kernel and device tree</h2>

<p>First, you have to get the <a href="https://downloads.raspberrypi.org">image</a> (in my case, I used a modified build of the bookworm image) and extract the “kernel” and the <a href="https://www.kernel.org/doc/html/latest/devicetree/usage-model.html">“device tree”</a> (to be honest, this was new for me when I read about this today).</p>

<p>We do this by mounting the boot partition and extracting the relevant files.</p>

<pre><code class="language-bash"># Check image partitions
$ fdisk -l ./HashiPi-pi0.img
</code></pre>

<p>Setup loop device with image, scan partitions. This is easier than fiddling with fdisk and partition offsets for mounting.</p>

<pre><code class="language-bash">$ sudo losetup -P /dev/loop0 HashiPi-pi0.img
$ sudo mount /dev/loop0p1 /mnt

# copy kernel and device tree binary (dtb)
$ cp /mnt/kernel8.img .
$ cp /mnt/bcm2711-rpi-4-b.dtb .

# unmount
$ sudo umount /mnt
$ sudo losetup --detach /dev/loop0
</code></pre>

<h2 id="patch-device-tree-to-enable-usb-controller">Patch device tree to enable USB controller</h2>

<p>The “device tree binary” (.dtb) needs to be translated into a readable <a href="https://www.kernel.org/doc/html/latest/devicetree/bindings/dts-coding-style.html">“device tree source” (.dts)</a> file.</p>

<pre><code class="language-bash">$ dtc -I dtb -O dts -o bcm2711-rpi-4-b.dts bcm2711-rpi-4-b.dtb
</code></pre>

<p>The .dts file can be <a href="https://github.com/trinitronx/qemu-raspbian">patched</a> to enable the usb controller. This is required, if we want to boot later using the <a href="https://en.wikipedia.org/wiki/Ethernet_over_USB">usbnet</a> device and port-forward (<a href="https://www.qemu.org/docs/master/system/qemu-manpage.html"><code>hostfwd</code></a>) the ssh port.</p>

<pre><code class="language-diff">--- bcm2711-rpi-4-b.dts.orig    2025-09-21 15:05:59.304575294 +0200
+++ bcm2711-rpi-4-b.dts 2025-09-21 15:04:56.709581742 +0200
@@ -1450,7 +1450,7 @@
                        phy-names = &#34;usb2-phy&#34;;
                        interrupt-names = &#34;usb&#34;, &#34;soft&#34;;
                        power-domains = &lt;0x10 0x06&gt;;
-                       status = &#34;disabled&#34;;
+                       status = &#34;okay&#34;;
                        phandle = &lt;0xbf&gt;;
                };
</code></pre>

<p>Unfortunately, we need to use this usb device, because all other emulated network devices are pci based which is <a href="https://www.qemu.org/docs/master/system/arm/raspi.html">not supported by QEMU for the Raspberry Pi</a></p>

<pre><code class="language-bash">$ qemu-system-aarch64 -device help
...
Network devices:
name &#34;e1000&#34;, bus PCI, alias &#34;e1000-82540em&#34;, desc &#34;Intel Gigabit Ethernet&#34;
name &#34;e1000-82544gc&#34;, bus PCI, desc &#34;Intel Gigabit Ethernet&#34;
name &#34;e1000-82545em&#34;, bus PCI, desc &#34;Intel Gigabit Ethernet&#34;
name &#34;e1000e&#34;, bus PCI, desc &#34;Intel 82574L GbE Controller&#34;
name &#34;i82550&#34;, bus PCI, desc &#34;Intel i82550 Ethernet&#34;
name &#34;i82551&#34;, bus PCI, desc &#34;Intel i82551 Ethernet&#34;
name &#34;i82557a&#34;, bus PCI, desc &#34;Intel i82557A Ethernet&#34;
name &#34;i82557b&#34;, bus PCI, desc &#34;Intel i82557B Ethernet&#34;
name &#34;i82557c&#34;, bus PCI, desc &#34;Intel i82557C Ethernet&#34;
name &#34;i82558a&#34;, bus PCI, desc &#34;Intel i82558A Ethernet&#34;
name &#34;i82558b&#34;, bus PCI, desc &#34;Intel i82558B Ethernet&#34;
name &#34;i82559a&#34;, bus PCI, desc &#34;Intel i82559A Ethernet&#34;
name &#34;i82559b&#34;, bus PCI, desc &#34;Intel i82559B Ethernet&#34;
name &#34;i82559c&#34;, bus PCI, desc &#34;Intel i82559C Ethernet&#34;
name &#34;i82559er&#34;, bus PCI, desc &#34;Intel i82559ER Ethernet&#34;
name &#34;i82562&#34;, bus PCI, desc &#34;Intel i82562 Ethernet&#34;
name &#34;i82801&#34;, bus PCI, desc &#34;Intel i82801 Ethernet&#34;
name &#34;igb&#34;, bus PCI, desc &#34;Intel 82576 Gigabit Ethernet Controller&#34;
name &#34;ne2k_pci&#34;, bus PCI
name &#34;pcnet&#34;, bus PCI
name &#34;rocker&#34;, bus PCI, desc &#34;Rocker Switch&#34;
name &#34;rtl8139&#34;, bus PCI
name &#34;tulip&#34;, bus PCI
-&gt; name &#34;usb-net&#34;, bus usb-bus
name &#34;virtio-net-device&#34;, bus virtio-bus # No &#39;virtio-bus&#39; bus found for device &#39;virtio-net-device&#39;
name &#34;virtio-net-pci&#34;, bus PCI, alias &#34;virtio-net&#34;
name &#34;virtio-net-pci-non-transitional&#34;, bus PCI
name &#34;virtio-net-pci-transitional&#34;, bus PCI
name &#34;vmxnet3&#34;, bus PCI, desc &#34;VMWare Paravirtualized Ethernet v3&#34;
</code></pre>

<p>We really need the usb device (virtio-net-device does not work either I tried), that&#39;s the reason for the patch.</p>

<p>A <a href="https://community.memfault.com/t/emulating-a-raspberry-pi-in-qemu-interrupt/684/10">comment</a> of the “interrupt.memfault blog” describes it nicely (very helpful community):</p>

<blockquote><p>Note that for raspi4, the bcm2711-rpi-4-b.dtb devicetree file has disabled the USB controller.
So, to enable USB keyboard &amp; mouse, the .dtb file must be decompiled to .dts,
patched, and recompiled back to .dtb.</p></blockquote>

<p>Unfortunately, it&#39;s not only needed for keyboard and mouse, but also to make our network adapter work (for ssh port-forwarding).</p>

<p>Thaa patching.. Then recompiling into binary form with <code>dtc</code>:</p>

<pre><code class="language-bash">$ dtc -I dtb -O dts -o bcm2711-rpi-4-b.dts bcm2711-rpi-4-b.dtb
</code></pre>

<p>Would be really nice to have this usb controller enabled by default in the next Trixie Pi OS 🤞</p>

<h2 id="boot-the-image">Boot the image</h2>

<p>For booting the image, I had to ensure two things for the kernel arguments for the Raspberry 4:</p>
<ul><li>Use the <code>ttyAMA1</code> console</li>
<li>Use the root partition <code>mmcblk1p2</code></li></ul>

<p>Note that I&#39;m not enabling the keyboard &amp; mouse devices (as suggested in the references online), because I&#39;m mainly interested to connect to the machine remotely via the ssh port fowarding:</p>

<pre><code class="language-bash">$ sudo qemu-system-aarch64 \
  -machine raspi4b -cpu cortex-a72 \
  -dtb bcm2711-rpi-4-b-mod.dtb \ # use mod device tree
  -m 2G -smp 4 \
  -kernel kernel8.img -sd HashiPi-pi0.img \
  -append &#34;rw earlyprintk loglevel=8 console=ttyAMA1,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk1p2 rootdelay=1&#34; \
  -device usb-net,netdev=net0 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22
</code></pre>

<p>That&#39;s it. Is still a bit slow, but good enough to throw some Ansible against the wall and see if it sticks.</p>

<p>My idea here is to do less with the HashiCorp packer scripts and go back to more Ansible, because that might be more sustainable in the long run.. Let&#39;s see. Next I&#39;m probably also going to give the Trixie (<a href="https://downloads.raspberrypi.org/nightlies/">nightly</a> image) a try.</p>

<h2 id="references">References</h2>
<ul><li><a href="https://interrupt.memfault.com/blog/emulating-raspberry-pi-in-qemu">https://interrupt.memfault.com/blog/emulating-raspberry-pi-in-qemu</a></li>
<li><a href="https://www.qemu.org/docs/master/system/qemu-manpage.html">https://www.qemu.org/docs/master/system/qemu-manpage.html</a></li>
<li><a href="https://www.qemu.org/docs/master/system/arm/raspi.html">https://www.qemu.org/docs/master/system/arm/raspi.html</a></li>
<li><a href="https://github.com/trinitronx/qemu-raspbian/blob/main/run-raspi4.sh">https://github.com/trinitronx/qemu-raspbian/blob/main/run-raspi4.sh</a></li>
<li><a href="https://github.com/trinitronx/qemu-raspbian/blob/main/bcm2711-rpi-4-b.dts.patch">https://github.com/trinitronx/qemu-raspbian/blob/main/bcm2711-rpi-4-b.dts.patch</a></li>
<li><a href="https://downloads.raspberrypi.org">https://downloads.raspberrypi.org</a></li>
<li><a href="https://www.man7.org/linux/man-pages/man8/losetup.8.html">https://www.man7.org/linux/man-pages/man8/losetup.8.html</a></li></ul>

<div style="text-align:center; font-size: 0.8em">
<a href="https://write.in0rdr.ch/feed">🛜 RSS</a> | <a href="https://m.in0rdr.ch/in0rdr">🐘 Fediverse</a> | <a href="https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch">💬 XMPP</a>
</div>
]]></content:encoded>
      <guid>https://write.in0rdr.ch/emulate-raspberry-pi4-on-qemu</guid>
      <pubDate>Sun, 21 Sep 2025 13:20:54 +0000</pubDate>
    </item>
    <item>
      <title>Borg2 backup with rclone</title>
      <link>https://write.in0rdr.ch/borg2-backup-with-rclone</link>
      <description>&lt;![CDATA[I recently started to figure out how to backup with Borg2 to cloud storage. Can be achieved conveniently since Borg2 2.0.0b11. At the time of this writing, I used 2.0.0b14. This post is simply a rambling on my backup journey to implement this in a semi-automated way on my Turris Omnia router.&#xA;&#xA;#borg #rclone #backup&#xA;!--more--&#xA;&#xA;A while ago I purchased quite some TB of storage at pCloud, a small Swiss cloud storage provider. Only recently, I found out that you can use rclone to push files and data to the cloud in an rsync-like fashion.&#xA;&#xA;Since I wanted to use that approach to backup files from my router, I first figured ways to install it with opkg. I followed the Turris docs to switch to a more recent feed/branch &#34;Here be Lions&#34; but noticed quickly, that I actually needed to install Borg2. What most distributions package nowadays is Borg (verison 1), which is the stable release. Borg2 is a breaking change (incompatible, but runs the new feature that supports rclone).&#xA;&#xA;Therefore, I decided to build a small Debian 12 lxc container and run Borg inside the container. That approach worked well.&#xA;&#xA;To mount a host path inside the container, I used the following modification of the lxc config file:&#xA;&#xA;Mount host ssd&#xA;lxc.mount.entry = /srv host-srv none bind,create=dir 0 0&#xA;&#xA;This will mount the /srv directory of the Turris host to the container, so the Borg process can backup files from that path.&#xA;&#xA;The rclone setup with pCloud was straight forward, I simply needed to confirm the login from my laptop with a browser, because the Turris cannot connect via browser to confirm the login on pCloud. Easy!&#xA;&#xA;The next step was configuring the Borg backup repository on pCloud.&#xA;&#xA;My borg configuration points to the backup folder on pCloud:&#xA;~/.config/borg/config &#xA;BORGREPO=&#39;rclone:pcloud:backup-folder&#39;&#xA;BORGPASSPHRASE=&#39;***&#39;&#xA;PATTERNSFILE=&#39;/root/.config/borg/patterns.lst&#39;&#xA;&#xA;I also maintain a patterns file, but won&#39;t go into details here.&#xA;&#xA;borg repo-create --encryption=repokey-chacha20-poly1305&#xA;&#xA;⚠️ Note that the repo-create and also a lot of other commands in Borg2 are similar, but different from the Borg v1 commands. A little bit confusing when reading the docs, but you&#39;ll get the hang of it..&#xA;&#xA;I chose to use chacha20-poly1305 encryption mode, because that combination was suggested to me as the fastest algorithm on my Turris. You can find out the speed of the different supported algorithms by running:&#xA;&#xA;borg benchmark cpu&#xA;&#xA;This is yet another convenient feature of Borg2.&#xA;&#xA;Lastly, I started the backup using a Systemd timer and some variation of borg create combined with another prune command to prune old backups.&#xA;&#xA;So far, so good. I&#39;m happy that I finally found a suitable solution for my backup. The process seems quite slow though. In my create borg command I included the --compression lz4 (which should be Speedy Gonzales), but more than 8h for the first backup? Common..&#xA;&#xA;speedy-gonzales&#xA;&#xA;I found a small signal trick that allowed me to check the current state of the upload process. This will show me the current file of the upload process:&#xA;&#xA;kill -s USR1 $(pidof python) &amp;&amp; journalctl -eu borg-backup | tail -1&#xA;&#xA;I could also contribute a small improvement in the Borg docs regarding the compilation of the dependencies required for Borg2 🎉 so the hassle was worth it.&#xA;&#xA;For automation of the entire procedure, I created a small packer build script that can rebuild the lxc container from scratch whenever needed. Essentially, it contains the commands to install the prerequisites for Borg on Debian followed by the installation with Pip in an virtual environment and the configuration with rclone.&#xA;&#xA;Edit 2024-12-17&#xA;&#xA;Turris Omnia Borg benchmark:&#xA;Chunkers =======================================================&#xA;buzhash,19,23,21,4095    1GB        12.052s&#xA;fixed,1048576            1GB        2.655s&#xA;Non-cryptographic checksums / hashes ===========================&#xA;xxh64                    1GB        2.394s&#xA;crc32 (zlib)             1GB        2.970s&#xA;Cryptographic hashes / MACs ====================================&#xA;hmac-sha256              1GB        10.785s&#xA;blake2b-256              1GB        24.264s&#xA;Encryption =====================================================&#xA;aes-256-ctr-hmac-sha256  1GB        39.176s&#xA;aes-256-ctr-blake2b      1GB        51.622s&#xA;aes-256-ocb              1GB        34.483s&#xA;chacha20-poly1305        1GB        12.335s&#xA;KDFs (slow is GOOD, use argon2!) ===============================&#xA;pbkdf2                   5          1.969s&#xA;argon2                   5          7.606s&#xA;Compression ====================================================&#xA;lz4          0.1GB      0.239s&#xA;zstd,1       0.1GB      0.739s&#xA;zstd,3       0.1GB      0.923s&#xA;zstd,5       0.1GB      16.528s&#xA;zstd,10      0.1GB      26.171s&#xA;zstd,16      0.1GB      51.617s&#xA;zstd,22      0.1GB      64.239s&#xA;zlib,0       0.1GB      0.703s&#xA;zlib,6       0.1GB      15.758s&#xA;zlib,9       0.1GB      16.217s&#xA;lzma,0       0.1GB      88.872s&#xA;lzma,6       0.1GB      114.931s&#xA;lzma,9       0.1GB      96.051s&#xA;msgpack ========================================================&#xA;msgpack      100k Items 0.818s&#xA;&#xA;For comparison, on my x230, where I would choose blake2 for hashing (blake2-chacha20-poly1305):&#xA;Chunkers =======================================================&#xA;buzhash,19,23,21,4095    1GB        1.360s&#xA;fixed,1048576            1GB        0.134s&#xA;Non-cryptographic checksums / hashes ===========================&#xA;xxh64                    1GB        0.097s&#xA;crc32 (zlib)             1GB        0.406s&#xA;Cryptographic hashes / MACs ====================================&#xA;hmac-sha256              1GB        3.474s&#xA;blake2b-256              1GB        1.980s&#xA;Encryption =====================================================&#xA;aes-256-ctr-hmac-sha256  1GB        3.901s&#xA;aes-256-ctr-blake2b      1GB        3.938s&#xA;aes-256-ocb              1GB        0.572s&#xA;chacha20-poly1305        1GB        1.251s&#xA;KDFs (slow is GOOD, use argon2!) ===============================&#xA;pbkdf2                   5          0.362s&#xA;argon2                   5          0.434s&#xA;Compression ====================================================&#xA;lz4          0.1GB      0.022s&#xA;zstd,1       0.1GB      0.041s&#xA;zstd,3       0.1GB      0.062s&#xA;zstd,5       0.1GB      0.104s&#xA;zstd,10      0.1GB      0.188s&#xA;zstd,16      0.1GB      13.794s&#xA;zstd,22      0.1GB      14.795s&#xA;zlib,0       0.1GB      0.067s&#xA;zlib,6       0.1GB      2.735s&#xA;zlib,9       0.1GB      2.740s&#xA;lzma,0       0.1GB      18.819s&#xA;lzma,6       0.1GB      36.049s&#xA;lzma,9       0.1GB      30.293s&#xA;msgpack ========================================================&#xA;msgpack      100k Items 0.258s&#xA;&#xA;div style=&#34;text-align:center; font-size: 0.8em&#34;&#xD;&#xA;a href=&#34;https://write.in0rdr.ch/feed&#34;&amp;#128732; RSS/a | a href=&#34;https://m.in0rdr.ch/in0rdr&#34;&amp;#128024; Fediverse/a | a href=&#34;https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch&#34;&amp;#128172; XMPP/a&#xD;&#xA;/div]]&gt;</description>
      <content:encoded><![CDATA[<p>I recently started to figure out how to backup with Borg2 to cloud storage. Can be achieved conveniently since <a href="https://github.com/borgbackup/borg/blob/master/docs/changes.rst#version-200b11-2024-09-26">Borg2 2.0.0b11</a>. At the time of this writing, I used 2.0.0b14. This post is simply a rambling on my backup journey to implement this in a semi-automated way on my Turris Omnia router.</p>

<p><a href="https://write.in0rdr.ch/tag:borg" class="hashtag"><span>#</span><span class="p-category">borg</span></a> <a href="https://write.in0rdr.ch/tag:rclone" class="hashtag"><span>#</span><span class="p-category">rclone</span></a> <a href="https://write.in0rdr.ch/tag:backup" class="hashtag"><span>#</span><span class="p-category">backup</span></a>
</p>

<p>A while ago I purchased quite some TB of storage at <a href="https://de.wikipedia.org/wiki/PCloud">pCloud</a>, a small Swiss cloud storage provider. Only recently, I found out that you can use <a href="https://en.wikipedia.org/wiki/Rclone">rclone</a> to push files and data to the cloud in an rsync-like fashion.</p>

<p>Since I wanted to use that approach to backup files from my router, I first figured ways to install it with opkg. I followed the Turris docs to switch to a <a href="https://gitlab.nic.cz/turris/os/build/blob/hbk/WORKFLOW.adoc#user-content-here-be-lions-hbl">more recent feed/branch “Here be Lions”</a> but noticed quickly, that I actually needed to install Borg2. What most distributions package nowadays is Borg (verison 1), which is the stable release. Borg2 is a breaking change (incompatible, but runs the new feature that supports rclone).</p>

<p>Therefore, I decided to build a small Debian 12 lxc container and run Borg inside the container. That approach worked well.</p>

<p>To mount a host path inside the container, I used the following modification of the lxc config file:</p>

<pre><code># Mount host ssd
lxc.mount.entry = /srv host-srv none bind,create=dir 0 0
</code></pre>

<p>This will mount the <code>/srv</code> directory of the Turris host to the container, so the Borg process can backup files from that path.</p>

<p>The <a href="https://rclone.org/pcloud/">rclone setup with pCloud</a> was straight forward, I simply needed to confirm the login from my laptop with a browser, because the Turris cannot connect via browser to confirm the login on pCloud. Easy!</p>

<p>The next step was configuring the Borg backup repository on pCloud.</p>

<p>My borg configuration points to the backup folder on pCloud:</p>

<pre><code># ~/.config/borg/config 
BORG_REPO=&#39;rclone:pcloud:backup-folder&#39;
BORG_PASSPHRASE=&#39;***&#39;
PATTERNSFILE=&#39;/root/.config/borg/patterns.lst&#39;
</code></pre>

<p>I also maintain a <a href="https://borgbackup.readthedocs.io/en/stable/usage/help.html#borg-patterns">patterns file</a>, but won&#39;t go into details here.</p>

<pre><code class="language-bash">borg repo-create --encryption=repokey-chacha20-poly1305
</code></pre>

<p>⚠️ Note that the <code>repo-create</code> and also a lot of other commands in Borg2 are similar, but different from the Borg v1 commands. A little bit confusing when reading the docs, but you&#39;ll get the hang of it..</p>

<p>I chose to use <a href="https://borgbackup.readthedocs.io/en/master/usage/repo-create.html#choosing-an-encryption-mode"><code>chacha20-poly1305</code> encryption mode</a>, because that combination was suggested to me as the fastest algorithm on my Turris. You can find out the speed of the different supported algorithms by running:</p>

<pre><code class="language-bash">borg benchmark cpu
</code></pre>

<p>This is yet another convenient feature of Borg2.</p>

<p>Lastly, I started the backup using a Systemd timer and some variation of <code>borg create</code> combined with another <code>prune</code> command to prune old backups.</p>

<p>So far, so good. I&#39;m happy that I finally found a suitable solution for my backup. The process seems quite slow though. In my <code>create</code> borg command I included the <code>--compression lz4</code> (which should be <a href="https://en.wikipedia.org/wiki/Speedy_Gonzales">Speedy Gonzales</a>), but more than 8h for the first backup? Common..</p>

<p><img src="https://upload.wikimedia.org/wikipedia/en/thumb/f/fe/Speedy_Gonzales.svg/220px-Speedy_Gonzales.svg.png" alt="speedy-gonzales"></p>

<p>I found a small signal trick that allowed me to check the current state of the upload process. This will <a href="https://github.com/borgbackup/borg/issues/2419">show me the current file of the upload</a> process:</p>

<pre><code class="language-bash">kill -s USR1 $(pidof python) &amp;&amp; journalctl -eu borg-backup | tail -1
</code></pre>

<p>I could also contribute a <a href="https://github.com/borgbackup/borg/pull/8586">small improvement</a> in the Borg docs regarding the compilation of the dependencies required for Borg2 🎉 so the hassle was worth it.</p>

<p>For automation of the entire procedure, I created a small packer build script that can rebuild the lxc container from scratch whenever needed. Essentially, it contains the commands to install the <a href="https://borgbackup.readthedocs.io/en/master/installation.html#debian-ubuntu">prerequisites for Borg on Debian</a> followed by the installation with Pip in an virtual environment and the configuration with rclone.</p>

<h3 id="edit-2024-12-17">Edit 2024-12-17</h3>

<p>Turris Omnia Borg benchmark:</p>

<pre><code>Chunkers =======================================================
buzhash,19,23,21,4095    1GB        12.052s
fixed,1048576            1GB        2.655s
Non-cryptographic checksums / hashes ===========================
xxh64                    1GB        2.394s
crc32 (zlib)             1GB        2.970s
Cryptographic hashes / MACs ====================================
hmac-sha256              1GB        10.785s
blake2b-256              1GB        24.264s
Encryption =====================================================
aes-256-ctr-hmac-sha256  1GB        39.176s
aes-256-ctr-blake2b      1GB        51.622s
aes-256-ocb              1GB        34.483s
chacha20-poly1305        1GB        12.335s
KDFs (slow is GOOD, use argon2!) ===============================
pbkdf2                   5          1.969s
argon2                   5          7.606s
Compression ====================================================
lz4          0.1GB      0.239s
zstd,1       0.1GB      0.739s
zstd,3       0.1GB      0.923s
zstd,5       0.1GB      16.528s
zstd,10      0.1GB      26.171s
zstd,16      0.1GB      51.617s
zstd,22      0.1GB      64.239s
zlib,0       0.1GB      0.703s
zlib,6       0.1GB      15.758s
zlib,9       0.1GB      16.217s
lzma,0       0.1GB      88.872s
lzma,6       0.1GB      114.931s
lzma,9       0.1GB      96.051s
msgpack ========================================================
msgpack      100k Items 0.818s
</code></pre>

<p>For comparison, on my x230, where <a href="https://borgbackup.readthedocs.io/en/master/usage/repo-create.html#choosing-an-encryption-mode">I would choose blake2 for hashing (<code>blake2-chacha20-poly1305</code>)</a>:</p>

<pre><code>Chunkers =======================================================
buzhash,19,23,21,4095    1GB        1.360s
fixed,1048576            1GB        0.134s
Non-cryptographic checksums / hashes ===========================
xxh64                    1GB        0.097s
crc32 (zlib)             1GB        0.406s
Cryptographic hashes / MACs ====================================
hmac-sha256              1GB        3.474s
blake2b-256              1GB        1.980s
Encryption =====================================================
aes-256-ctr-hmac-sha256  1GB        3.901s
aes-256-ctr-blake2b      1GB        3.938s
aes-256-ocb              1GB        0.572s
chacha20-poly1305        1GB        1.251s
KDFs (slow is GOOD, use argon2!) ===============================
pbkdf2                   5          0.362s
argon2                   5          0.434s
Compression ====================================================
lz4          0.1GB      0.022s
zstd,1       0.1GB      0.041s
zstd,3       0.1GB      0.062s
zstd,5       0.1GB      0.104s
zstd,10      0.1GB      0.188s
zstd,16      0.1GB      13.794s
zstd,22      0.1GB      14.795s
zlib,0       0.1GB      0.067s
zlib,6       0.1GB      2.735s
zlib,9       0.1GB      2.740s
lzma,0       0.1GB      18.819s
lzma,6       0.1GB      36.049s
lzma,9       0.1GB      30.293s
msgpack ========================================================
msgpack      100k Items 0.258s
</code></pre>

<div style="text-align:center; font-size: 0.8em">
<a href="https://write.in0rdr.ch/feed">🛜 RSS</a> | <a href="https://m.in0rdr.ch/in0rdr">🐘 Fediverse</a> | <a href="https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch">💬 XMPP</a>
</div>
]]></content:encoded>
      <guid>https://write.in0rdr.ch/borg2-backup-with-rclone</guid>
      <pubDate>Mon, 16 Dec 2024 21:27:15 +0000</pubDate>
    </item>
  </channel>
</rss>