<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Backup on Sysadmin Tales</title>
    <link>https://blog.ssb-tech.net/tags/backup/</link>
    <description>Recent content in Backup 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/backup/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>
  </channel>
</rss>
