<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Zfs on Sysadmin Tales</title>
    <link>https://blog.ssb-tech.net/tags/zfs/</link>
    <description>Recent content in Zfs on Sysadmin Tales</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 02 Oct 2026 21:39:10 -0400</lastBuildDate>
    <atom:link href="https://blog.ssb-tech.net/tags/zfs/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Deduplicated Proxmox backups with Proxmox Backup Server and ZFS</title>
      <link>https://blog.ssb-tech.net/posts/proxmox-pbs-zfs/</link>
      <pubDate>Wed, 22 Apr 2026 23:23:10 +0000</pubDate>
      <guid>https://blog.ssb-tech.net/posts/proxmox-pbs-zfs/</guid>
      <description>&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;&#xA;&lt;p&gt;There are many ways to back up your &lt;a href=&#34;https://proxmox.com/en/products/proxmox-virtual-environment/overview&#34;&gt;Proxmox&lt;/a&gt; virtual machines.&lt;/p&gt;&#xA;&lt;p&gt;One of the most popular ways to do so is via &lt;a href=&#34;https://proxmox.com/en/products/proxmox-backup-server/overview&#34;&gt;Proxmox Backup Server&lt;/a&gt;, which gives you many advantages:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Deduplication of common data.&lt;/li&gt;&#xA;&lt;li&gt;The ability to cherry pick files out of your backups.&lt;/li&gt;&#xA;&lt;li&gt;Tight integration with the Proxmox ecosystem.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;However, how is one to achieve proper 3-2-1 backups using this mechanism?&lt;/p&gt;&#xA;&lt;p&gt;One way is to run multiple datastores, some local and some using Amazon S3 compatible endpoints.&lt;/p&gt;&#xA;&lt;p&gt;However, this is a bit much for me, so I came up with a simpler method.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-details&#34;&gt;The Details&lt;/h2&gt;&#xA;&lt;p&gt;I run my PBS on a &lt;a href=&#34;https://www.amazon.com/dp/B0BVFKN7ZL&#34;&gt;Beelink N100 mini PC&lt;/a&gt;, in which I&amp;rsquo;ve installed a 2TB SATA SSD that I formatted as a single disk zpool.&lt;/p&gt;&#xA;&lt;p&gt;I then installed Jim Salter&amp;rsquo;s excellent &lt;a href=&#34;https://github.com/jimsalterjrs/sanoid&#34;&gt;Sanoid&lt;/a&gt; utility, configuring ZFS snapshots on the PBS server.&lt;/p&gt;&#xA;&lt;p&gt;This is the &lt;code&gt;/etc/sanoid.conf&lt;/code&gt; that I&amp;rsquo;ve defined. You can, of course, set whatever values you like.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[pbs-local/datastore]&#xA;        use_template = pbs&#xA;        recursive = yes&#xA;&#xA;[template_pbs]&#xA;        frequently = 0&#xA;        hourly = 36&#xA;        daily = 3&#xA;        weekly = 1&#xA;        monthly = 0&#xA;        yearly = 0&#xA;        autosnap = yes&#xA;        autoprune = yes&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, once I had my initial snapshots, I went to my TrueNAS backup server and created a new ZFS replication task.&lt;/p&gt;&#xA;&lt;p&gt;I used this to &lt;em&gt;pull&lt;/em&gt; the snapshots for the datastore to the backup server.&lt;/p&gt;&#xA;&lt;p&gt;The key is to match the expected snapshot naming schema for Sanoid, like so:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;Screenshot showing TrueNAS replication task with proper naming scheme for Sanoid&#34; loading=&#34;lazy&#34; src=&#34;https://blog.ssb-tech.net/posts/proxmox-pbs-zfs/images/truenas-sanoid.png&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This allows me to maintain the deduplicated nature of the Proxmox Backup Server datastore.&lt;/p&gt;&#xA;&lt;p&gt;You can do the same with any offsite NAS that you may have, as long as it&amp;rsquo;s running ZFS. This is easily accomplished with something like &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; or &lt;a href=&#34;https://netbird.io/&#34;&gt;Netbird&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If I ever have a failure of the Proxmox Backup Server, I can simply set up a new zpool on the repaired system and reverse the direction of the replication.&lt;/p&gt;&#xA;&lt;p&gt;I also use &lt;a href=&#34;https://klarasystems.com/articles/improving-replication-security-with-openzfs-delegation/&#34;&gt;ZFS Delegation&lt;/a&gt; to avoid doing the replication as root, but I&amp;rsquo;ve &lt;a href=&#34;https://blog.ssb-tech.net/posts/truenas-zfs-replication-without-root/&#34;&gt;covered this topic before&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;As always - trust nothing and test those backups!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>TrueNAS Scale - ZFS Replication Without Root</title>
      <link>https://blog.ssb-tech.net/posts/truenas-zfs-replication-without-root/</link>
      <pubDate>Fri, 21 Mar 2025 15:15:20 -0400</pubDate>
      <guid>https://blog.ssb-tech.net/posts/truenas-zfs-replication-without-root/</guid>
      <description>&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;&#xA;&lt;p&gt;ZFS replication is my favored way of doing backups. In my homelab I have 2 systems running TrueNAS scale - one on my production hypervisor, with the disk controller passed through, and the backup server, which is just a baremetal TrueNAS Scale installation.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately, most of the tutorials on this process seem to use either the root account or at the very least, an account with admin privileges. In this article, I&amp;rsquo;m going to go over how you can get a ZFS replication setup working with a completely unprivileged user, without ever leaving the GUI.&lt;/p&gt;&#xA;&lt;p&gt;I will be doing a &lt;em&gt;pull replication&lt;/em&gt; - where the production system has NO access to the backup system. The backup system will reach out and initiate the backups.&lt;/p&gt;&#xA;&lt;p&gt;That way, there&amp;rsquo;s no risk of the backup server being compromised because you had SSH credentials for it just lying around on production.&lt;/p&gt;&#xA;&lt;p&gt;You should also lock down access to the backup system in other ways, but that&amp;rsquo;s beyond the scope of this article.&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-user-accounts-for-backup&#34;&gt;Create user accounts for backup&lt;/h2&gt;&#xA;&lt;p&gt;Go to Credentials &amp;gt; Users and create new users. Just create normal user accounts. Don&amp;rsquo;t give it any extra permissions. I also recommend &lt;em&gt;unchecking&lt;/em&gt; the box that allows it to be used for SMB authentication.&lt;/p&gt;&#xA;&lt;p&gt;Make sure that you change the login shell from &amp;ldquo;nologin&amp;rdquo; to &amp;ldquo;bash&amp;rdquo; or &amp;ldquo;zsh&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I normally just call mine backup_user, but you can make it anything you want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-ssh-credentials&#34;&gt;Create SSH credentials&lt;/h2&gt;&#xA;&lt;h3 id=&#34;on-the-backup-system&#34;&gt;On the backup system:&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Click Credentials &amp;gt; Backup Credentials&lt;/li&gt;&#xA;&lt;li&gt;Add an SSH Keypair. Give it a name. Click on generate keypair.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This will generate a PUBLIC key and a PRIVATE key. The private key will be used on the backup system to verify the public key.&lt;/li&gt;&#xA;&lt;li&gt;I recommend copying the public key into a notepad or something. We&amp;rsquo;ll need it again in a moment.&lt;/li&gt;&#xA;&lt;li&gt;Click Save.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Add a new SSH Connection. Name it something that makes sense.&lt;/li&gt;&#xA;&lt;li&gt;Setup method - manual&lt;/li&gt;&#xA;&lt;li&gt;For host, enter the IP address of the production system. If your machine is offsite and you have them both connected via &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt;, you can use the Tailscale IP here, &lt;em&gt;even if the machine is local&lt;/em&gt;. Tailscale connections are designed to be peer-to-peer, so it should stay in the same local network and get the full wire rate.&lt;/li&gt;&#xA;&lt;li&gt;For username, change it to the username of the user you created on the REMOTE system. That is, the PRODUCTION system.&lt;/li&gt;&#xA;&lt;li&gt;Select the private key you created in step 2.&lt;/li&gt;&#xA;&lt;li&gt;Click &amp;ldquo;Discover remote host key&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Click Save.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;on-the-production-system&#34;&gt;On the production system:&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Navigate to Credentials &amp;gt; Users. Edit the user you created for your backup tasks.&lt;/li&gt;&#xA;&lt;li&gt;Take the public key you copied earlier and paste it into the Authorized Keys field. (Or upload it if you saved it as a file.)&lt;/li&gt;&#xA;&lt;li&gt;Click save.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;giving-users-needed-permissions&#34;&gt;Giving users needed permissions&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Because we&amp;rsquo;re not using the root user, we need to give our backup users the ability to run certain commands with sudo, without a password. &lt;strong&gt;None of these commands can be used destructively.&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;Navigate back to Credentials &amp;gt; Users. Edit the backup user.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;on-the-backup-system-1&#34;&gt;On the backup system:&lt;/h3&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;Type the following into the &amp;ldquo;Allowed sudo commands with no password&amp;rdquo; box. The asterisks are wildcards.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/sbin/zfs mount *&#xA;/sbin/zfs create *&#xA;/sbin/zfs receive *&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;on-the-production-system-1&#34;&gt;On the production system:&lt;/h3&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;Type the following into the &amp;ldquo;Allowed sudo commands with no password&amp;rdquo; box. The asterisks are wildcards.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/sbin/zfs send *&#xA;/sbin/zfs snapshot *&#xA;/sbin/zfs list *&#xA;/sbin/zfs get *&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will allow a completely unprivileged user to run the backups for us.&lt;/p&gt;&#xA;&lt;h2 id=&#34;creating-the-replication-task&#34;&gt;Creating the replication task&lt;/h2&gt;&#xA;&lt;h3 id=&#34;on-the-backup-system-2&#34;&gt;On the backup system:&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Navigate to Data Protection &amp;gt; Replication Tasks. Click Add.&lt;/li&gt;&#xA;&lt;li&gt;For the source location, choose &amp;ldquo;On a different system&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Choose the SSH connection we created earlier.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When prompted if you would like to use sudo for ZFS commands, allow it. This is needed because the user we&amp;rsquo;re doing this operation with does not have admin privileges.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;For the source, choose the dataset that you would like to back up. I usually also check off the recursive box, though this has no effect unless you&amp;rsquo;ve created nested datasets.&lt;/li&gt;&#xA;&lt;li&gt;For the destination, choose either the pool itself or the dataset ABOVE the one you want to replicate to. &lt;strong&gt;The dataset CANNOT exist prior to the first replication. It will fail if you create it in advance.&lt;/strong&gt; You&amp;rsquo;ll need to type in the name of the dataset in the text box. This is slightly unintuitive, I know. I don&amp;rsquo;t know why they did it this way.&lt;/li&gt;&#xA;&lt;li&gt;Choose a schedule and a retention policy.&lt;/li&gt;&#xA;&lt;li&gt;Run your first replication. The first one will take a long time if there is a lot of data to copy, but subsequent runs will take only as much time as it takes to send the changed blocks down the wire.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Keep in mind when choosing your retention policies on the source and destination systems that &lt;strong&gt;the source and destination systems NEED to have at least one snapshot in common!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Happy replicating!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Fedora 41 and ZFS</title>
      <link>https://blog.ssb-tech.net/posts/fedora41-and-zfs/</link>
      <pubDate>Mon, 09 Dec 2024 20:40:18 -0500</pubDate>
      <guid>https://blog.ssb-tech.net/posts/fedora41-and-zfs/</guid>
      <description>&lt;div class=&#34;callout callout-note&#34; role=&#34;note&#34;&gt;&lt;div class=&#34;callout-title&#34;&gt;Note&lt;/div&gt;&lt;div class=&#34;callout-content&#34;&gt;ZFS 2.2.7 has been released with up to Linux kernel 6.12 support, so this workaround is no longer necessary.&#xA;I&amp;rsquo;ll leave the post up in case this is ever useful in the future.&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I previously posted about how to &lt;a href=&#34;https://blog.ssb-tech.net/posts/building-fedora-server-into-a-desktop/&#34;&gt;build a desktop OS from the Fedora Server installer&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This is a bit of a follow up to that post.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve now been running Fedora 41 for a few days and it&amp;rsquo;s been a mostly pleasant experience.&lt;/p&gt;&#xA;&lt;p&gt;However, I am also an avid ZFS user, and the current stable release of OpenZFS &lt;a href=&#34;https://github.com/openzfs/zfs/issues/16590&#34;&gt;does not support Linux kernel 6.11 yet&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;So, being the enterprising fellow that I am, I chose to build ZFS 2.3.0 RC3 from source using the &lt;a href=&#34;https://openzfs.github.io/openzfs-docs/Developer%20Resources/Building%20ZFS.html&#34;&gt;official instructions&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;That went well, but one thing that tripped me up (and caused some issues for specific applications like syncthing, which keeps it&amp;rsquo;s local database in the user&amp;rsquo;s home directory) is that when you do this, unlike when you install &lt;code&gt;zfsutils-linux&lt;/code&gt; on Ubuntu, it doesn&amp;rsquo;t set up the automatic import and mounting of your pool.&lt;/p&gt;&#xA;&lt;p&gt;It took some digging around to find the correct process, because it seems to be a bit different between the official ZFS source and the one that ships with Ubuntu, but here&amp;rsquo;s what wound up working for me:&lt;/p&gt;&#xA;&lt;p&gt;First, go through and enable the following services:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable zfs.target zfs-mount.target zfs-import.target zfs-import-cache.service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are plenty of posts online telling you that you should create your cache file in &lt;code&gt;/etc/zfs/zfs-list-cache/&lt;/code&gt;, but this is wrong (or at least outdated. I’m not sure if that location is Ubuntu specific?)&lt;/p&gt;&#xA;&lt;p&gt;The ACTUAL location of the cache file (which you can see if you actually read through the systemd unit file for zfs-import-cache.service) is &lt;code&gt;/usr/local/etc/zfs&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If the file doesn&amp;rsquo;t exist, create it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo touch /usr/local/etc/zfs/zpool.cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Import your pool.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo zpool import poolname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you print out the cache file now it should no longer be empty.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /usr/local/etc/zfs/zpool.cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next time you reboot your pools should automatically mount and mount all filesystems.&lt;/p&gt;&#xA;&lt;p&gt;And yes, I did cross post this over on the &lt;a href=&#34;https://discourse.practicalzfs.com/t/psa-zfs-automount-when-building-from-source/1970/1&#34;&gt;PracticalZFS forum.&lt;/a&gt;&lt;/p&gt;&#xA;</description>
    </item>
  </channel>
</rss>
