Per official documentation, it is recommended that users download latest templates through qvm-template
before "switching" everything from a pre-existing template to the newer template. qvm-prefs
allows for a somewhat seamless transition of preferences. But inheritance and persistence is a bit more complicated for the non-technical user.
This makes upgrading-in-place a very attractive option for new and experienced users alike. Fedrora documentation and Debian documentation suggest this process is for the "advanced" user. This should not be the case.
Include as a qubes command the option to "upgrade-in-place" a template, perhaps qvm-upgrade-debian
and qvm-upgrade-fedora
. I've provided basic Bash scripts for doing so, with an option for upgrading multiple templates of the same distro at once:
For Fedora-based templates. For Debian-based templates.
At present, both scripts were tested successfully for upgrading Fedora-37 to Fedora-38 and Debian-11 to Debian-12. These scripts might also benefit from qvm-clone
commands to create .bak templates and a help/usage function.
#!/bin/env bash
# A simple script for updating Debian templates in QubesOS
# Debian 12 "Bookworm"
# Debian 13 "Trixie"
PREFIX="$(tput setaf 7)$(tput bold)"
YELLOW="$(tput setaf 3)$(tput bold)"
POSTFIX="$(tput sgr0)"
TAB="$(echo -e '\t')"
message() {
echo "${PREFIX}${1}${POSTFIX}"
}
upgrade_template() {
local template=$1
local proceed=$2
local clone=$3
local new_template_name=$4
local old_name=$5
local new_name=$6
vm_exists=$(qvm-ls | grep -w "$template")
if [[ -z $vm_exists ]]; then
message "Template $template does not exist."
exit 1
fi
if [[ $proceed != "y" ]]; then
message "Skipping $template without changes."
return 0
fi
if [[ $clone == "y" ]]; then
qvm-clone $template $new_template_name
else
new_template_name=$template
fi
message "Upgrading $new_template_name"
qvm-run -a $new_template_name gnome-terminal
message "Updating APT repositories..."
qvm-run -p $new_template_name "sudo sed -i 's/$old_name/$new_name/g' /etc/apt/sources.list"
qvm-run -p $new_template_name "sudo sed -i 's/$old_name/$new_name/g' /etc/apt/sources.list.d/qubes-r4.list"
message "Performing upgrade..."
qvm-run -p $new_template_name "sudo apt update && sudo apt upgrade && sudo apt dist-upgrade -y"
qvm-run -p $new_template_name "sudo apt-get autoremove && sudo apt-get clean"
message "Trimming the new template..."
qvm-run -p $new_template_name "sudo fstrim -av"
qvm-shutdown $new_template_name
qvm-start $new_template_name
qvm-run -p $new_template_name "sudo fstrim -av"
message "Shutting down $new_template_name"
qvm-shutdown $new_template_name
}
prompt_user() {
message "Upgrade Debian template in QubesOS"
read -p "Which template do you want to upgrade? " template
read -p "Proceed with the upgrade? (y/n): " proceed
if [[ $proceed != "y" ]]; then
message "Exiting without changes."
exit 0
fi
read -p "Do you want to clone the template before upgrading? (y/n): " clone
read -p "What should be the new template name? " new_template_name
read -p "Enter the old release name (e.g., buster): " old_name
read -p "Enter the new release name (e.g., bullseye): " new_name
}
if [ $# -eq 0 ]; then
prompt_user
upgrade_template $template $proceed $clone $new_template_name $old_name $new_name
else
message "Usage: $0"
exit 1
fi
if [ $# -eq 0 ]; then
cat >&2 <<-EOF
Usage: ${0##*/} [options] -t
...
EOF
fi
#!/bin/env bash
# A simple script for updating Fedora templates in QubesOS
PREFIX="$(tput setaf 7)$(tput bold)"
YELLOW="$(tput setaf 3)$(tput bold)"
POSTFIX="$(tput sgr0)"
TAB="$(echo -e '\t')"
ENTER=""
message() {
echo "${PREFIX}${1}${POSTFIX}"
}
upgrade_template() {
local template=$1
local proceed=$2
local clone=$3
local new_template_name=$4
vm_exists=$(qvm-ls | grep -w "$template")
if [[ -z $vm_exists ]]; then
message "Template $template does not exist."
exit 1
fi
current_version=$(qvm-run -p $template "cat /etc/fedora-release")
current_num=$(echo $current_version | grep -oP '(\d+)')
if [[ $proceed != "y" ]]; then
message "Skipping $template without changes."
return 0
fi
new_num=$((current_num + 1))
new_release="fedora-$new_num"
if [[ $clone == "y" ]]; then
qvm-clone $template $new_template_name
else
new_template_name=$template
fi
message "Allocating additional space..."
truncate -s 5GB /var/tmp/template-upgrade-cache.img
dev=$(sudo losetup -f --show /var/tmp/template-upgrade-cache.img)
message "Attaching block to $new_template_name"
qvm-start $new_template_name
qvm-block attach $new_template_name dom0:${dev##*/}
qvm-run -p $new_template_name "sudo mkfs.ext4 /dev/xvdi"
qvm-run -p $new_template_name "sudo mount /dev/xvdi /mnt/removable"
message "Performing upgrade. Patience..."
if qvm-run -p $new_template_name "sudo dnf clean all && sudo dnf --releasever=$new_num distro-sync --best --allowerasing -y";
then
qvm-run -p $new_template_name "sudo dnf update -y && sudo dnf upgrade -y"
qvm-run -p $new_template_name "cat /etc/fedora-release"
qvm-shutdown $new_template_name
sleep 2
message "Removing temporary cache..."
sudo losetup -d $dev
rm -f /var/tmp/template-upgrade-cache.img
sleep 2
message "Upgrade completed successfully!"
else
message "Upgrade failed. Check the template for issues."
exit 1
fi
}
prompt_user() {
current_version=$(qvm-run -p $template "cat /etc/fedora-release")
current_num=$(echo $current_version | grep -oP '(\d+)')
message "Current version of $template is: Fedora release $current_num ${YELLOW} "
read -p "Proceed with the upgrade? (y/n): " proceed
if [[ $proceed != "y" ]]; then
message "Skipping $template without changes."
exit 0
fi
read -p "Do you want to clone the template before upgrading? (y/n): " clone
}
get_new_template_name() {
if [[ $clone == "y" ]]; then
read -p "What should be the new template name? " new_template_name
echo $new_template_name
else
echo $1
fi
}
if [ $# -gt 0 ]; then
for template in "$@"; do
prompt_user
new_template_name=$(get_new_template_name $template)
upgrade_template $template $proceed $clone $new_template_name
done
else
read -p "What template do you want to upgrade? " template
prompt_user
new_template_name=$(get_new_template_name $template)
upgrade_template $template $proceed $clone $new_template_name
fi
if [ $# -eq 0 ]; then
cat >&2 <<-EOF
Usage: ${0##*/} [options] -t
...
EOF
fi
Such scripts would lower the barrier-to-entry for non-technical users interested in adopting Qubes. Furthermore, it would lower the amount of time spent on upgrading individual templates a user may have created based on the defaults, becoming a value-add. It would also limit bandwidth on current Qubes documentation.
I'm hoping more tech-savy users can assist in following on the thread with @marmarek and others as I've no longer the bandwidth to pursue.
https://github.com/QubesOS/qubes-issues/issues/8605
@mods if this is in the wrong sub-forum, please let me know and I can revert elsewhere. Thanks to all in advance.