16 August 2026

Proxmox 8 to 9 upgrade

As the Proxmox 8 EOL was coming up fast (2026-08-31), I needed to do the upgrade.


Prepare for Upgrade

 Ran pve8to9 and then pve8to9 --full

  • suggested to install intel-microcode
  • added non-free and non-free-firmware to /etc/apt/sources.list
  • apt update
  • apt install intel-microcode


Ensured Proxmox 8 was up to date

  • apt update
  • apt dist-upgrade
  • pveversion


Perform the Upgrade

Replace bookworm with trixie

  • sed -i 's/bookworm/trixie/g' /etc/apt/sources.list
  • Add a proxmox.sources:

cat > /etc/apt/sources.list.d/proxmox.sources << EOF
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF

  • Remove outdated Proxmox source (may not exist on your system)
    • rm /etc/apt/sources.list.d/pve-install-repo.list


Ensure the apt sources changes worked

  • apt update


Perform the upgrade (recommend doing ti from ssh shell and not Proxmox web shell)

  • apt dist-upgrade


Reboot

  • shutdown -r now


After install cleanup

Comment out the Enterprise source and test it:

  • /etc/apt/sources.list.d/pve-enterprise.sources
  • apt update


Migrate to the new .sources format:

  • apt modernize-sources
  • apt update


Appendix

Sources





02 August 2026

Sending ZFS backups to another server

After migrating back to my Lenovo server, it didn't have enough drive bays for my backup drives. So I needed to use the Dell as the backup destination.

Two servers:

  • Primary: this is the main server where the primary copy of the data exists (Lenovo)
  • Secondary: this is the backup server where we will send the data to a read-only copy (Dell)


Setup SSH

On the primary server, create ssh key pair (if you already have a key pair feel free to use that):

  • ssh-keygen -t ed25519 -C "root@primary"
    • -C is just a comment to allow for easier identification, so feel free to change, but make sure you also change where it is used later
  • cat id_ed25519.pub
    • We will need this output for saving the key


On the secondary server, create our backup user and give it the public key:

  • Install sudo
    • apt install sudo -y
  • Add the pveadmin user
    • adduser pveadmin
    • usermod -aG sudo pveadmin
    • # Allow pveadmin to run certain commands without prompting for password so use visudo to add the line
    • visudo
      • pveadmin ALL=(ALL) NOPASSWD: /usr/sbin/zfs list *, /usr/sbin/zfs receive *, /usr/sbin/zpool scrub *
  • Switch to the pveadmin user and add our ssh key
    • su - pveadmin
    • mkdir ~/.ssh
    • chmod 700 ~/.ssh
    • # Change the below to your key
    • echo "ssh-ed25519 ABCD1234... root@primary" >> ~/.ssh/authorized_keys
    • chmod 600 ~/.ssh/authorized_keys
    • exit
  • Test the ssh from primary to secondary and save the fingerprint
    • ssh pveadmin@secondary


Send the backups

  • Send over our initial data (use disown to prevent user disconnections from stopping job)
    • zfs send -R --raw rpool/data@backup-20260323 | ssh pveadmin@secondary "sudo zfs receive -o readonly=on backup-pool/data" 2>errors.log & disown
  • Send over incremental data
    • zfs send -R --raw -I rpool/data@backup-20260323 rpool/data@backup-20260401 | ssh pveadmin@secondary "sudo zfs receive backup-pool/data" 2>errors.log & disown


Automate the backups

  • Added a remote argument to my backup.sh script


Scripts

remote-backup.sh

#!/bin/sh

if [ $# -ne 3 ] ; then
  echo "Requires 3 args source, destination, and user@host"
  exit 1
fi

src=$1
dest=$2
remote=$3

snaplist=$(zfs list -t snapshot $src)
if [ $? -ne 0 ] ; then
  echo "No snapshots found for $src"
  exit 1
fi

bkpsnap=$(ssh ${remote} "sudo zfs list -t snapshot $dest 2>&1")
incremental=$?

if [ $incremental -eq 0 ] ; then
  incsnap=$(echo "$bkpsnap" | tail -n 1 | cut -f1 -d" " | cut -f2 -d"@")
  snap=$(echo "$snaplist" | grep "$incsnap" -A 1 | tail -n 1 | cut -f1 -d" " | cut -f2 -d"@")

  if [ "$incsnap" = "$snap" ] ; then
    echo "Backup is already up to date"
    exit 1
  fi

  echo "Sending incremental snap $src@$snap on top of $dest@$incsnap"
  echo "zfs send -R --raw -I $src@$incsnap $src@$snap | ssh ${remote} \"sudo zfs receive $dest\""
  zfs send -R --raw -I $src@$incsnap $src@$snap | ssh ${remote} "sudo zfs receive $dest"
else
  snap=$(echo "$snaplist" | tail -n +2 | head -n 1 | cut -f1 -d" " | cut -f2 -d"@")
  echo "Sending initial snap $src@$snap to $dest"
  echo "zfs send -R --raw $src@$snap | ssh ${remote} \"sudo zfs receive -o readonly=on $dest\""
  zfs send -R --raw $src@$snap | ssh ${remote} "sudo zfs receive -o readonly=on $dest"
fi

echo "Complete\n"


Appendix

Sources