File tik-1.1.9.obscpio of Package tik
07070100000000000081A40000000000000000000000016672CAA800000454000000000000000000000000000000000000001200000000tik-1.1.9/LICENSEMIT License
Copyright (c) 2023-2024 SUSE LLC
Copyright (c) 2023-2024 Richard Brown
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
07070100000001000081A40000000000000000000000016672CAA800000D2E000000000000000000000000000000000000001400000000tik-1.1.9/README.md# tik
Transactional Installation Kit - A toolkit for deploying Operating System images to UEFI hardware from a USB stick.
## General Premise
A simple, lightweight, extensible tool for deploying a premade OS images to UEFI hardware.
tik was originally inspired by the "SelfInstaller" functionality offered by [kiwi](https://github.com/OSInside/kiwi) OEM images, but is designed to be wholly independent of the toolchain used to create the OS images.
It's core functionality is very similar to kiwi's SelfInstaller, with the basic workflow for deploying an image being a very simple process:
- Identify storage devices on the system
- Offer the user a list of available devices
- Deploy image to that device
In addition to the above workflow, tik supports the following additional features
- Unattended automation of the deployment of the image
- Optional extensions to be run before or after the deployment of the image (eg to support functionality like checking the network for an updated image). This functionality is inspired by [jeos-firstboot](https://github.com/openSUSE/jeos-firstboot/)'s module support
- Support for multiple images provided on the same installation media (eg. openSUSE Aeon and openSUSE MicroOS)
## tik OS Images
tik is designed to deploy a .raw/.img disk image, which is expected to contain
- the full partition table
- a UEFI ESP/EFI partition
- 1 (or more) OS partitions
tik should not care about the contents of the disk image, which potentially could be of any Operating System built using any toolset (eg kiwi, mkosi, etc)
Features like expanding the partitions to fill the disk are expected to be handled by tools like systemd-repart on the booting of the deployed OS, not by tik (though in theory optional extensions could be written to impliment this)
## tik Installation Media
tik is designed to be run on a different style of media than many traditional OS installers
Traditional tooling like YaST, Agama, Windows Installer, etc are all expected to be read-only Installation media that aren't modifiable by the user at all
tik Installtion Media are expected to be a variant of openSUSE MicroOS, designed to be run from portable media (eg a USB stick)
while the "Install OS" of the Installation Media will therefore be read-only when in use, the "Install OS" will be possible of being updated and configured to the users needs, directly on the USB stick after it's imaged
More importantly, this also means that the Installation Media will have various read-write locations, including /var/lib/tik/images, the location of tiks .raw/.img files, allowing users to add their own custom variants of such images to be offered when the tik installer boots up
## tik + ignition + combustion
because tik installation media are built separately from the Operating System(s) which tik will offer to deploy, this means that tik installation images can also contain a separate 'ignition/combustion partition' which can have your ignition/combustion configurations stored within
These will then be automatically used by any OS image which uses ignition or combustion (eg openSUSE MicroOS) on their first boot after tik has deployed an image, assuming the tik Installation USB stick is still connected
This makes ignition and/or combustion the perfect tools for making any automated customisations to any OS image deployed via tik
07070100000002000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000000E00000000tik-1.1.9/etc07070100000003000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001200000000tik-1.1.9/etc/tik07070100000004000081A40000000000000000000000016672CAA800000377000000000000000000000000000000000000001900000000tik-1.1.9/etc/tik/config# Directory for users to add custom configuration and modules
# Default: "/etc/tik"
#TIK_CUSTOM_DIR="/etc/tik"
# Directory for OS images to be deployed
# Default: "/usr/lib/tik/img"
#TIK_IMG_DIR="/usr/lib/tik/img"
# To show USB devices in the install device selection dialog, uncomment this variable
# USB devices are filtered out by default
#TIK_ALLOW_USB_INSTALL_DEVICES=1
# For unattended installations the disk device to deploy the image must be defined if more than one is present
# Default: Undefined
#TIK_INSTALL_DEVICE=""
# For unattended installations the disk image to deploy must be defined if more than one is present
# Default: Undefined
#TIK_INSTALL_IMAGE=""
# Display name of the OS to be deployed by tik
# Default: Undefined
#TIK_OS_NAME=""
# URL for bug reports to go to
# Default: https://aeondesktop.org/reportbug
#TIK_BUG_URL="https://aeondesktop.org/reportbug"07070100000005000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000000E00000000tik-1.1.9/usr07070100000006000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001200000000tik-1.1.9/usr/bin07070100000007000081ED0000000000000000000000016672CAA8000006D2000000000000000000000000000000000000001600000000tik-1.1.9/usr/bin/tik#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2023-2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2023-2024 Richard Brown
# Define variables
# Style notes
# lowercase variables = internal, not expected to be defined by users
# uppercase variables = user facing, expected to be set by config
tik_log=~/tik.log
tik_dir=/usr/lib/tik
tik_module="tik"
# Read libraries
. ${tik_dir}/lib/tik-functions
# Start logging
exec 2> >(exec tee -i -a "${tik_log}" >&2)
log "[START] $0"
# Check for debug mode
if [[ $1 == "--debug" ]]; then
debug=1
fi
# Read configuration files, /usr first, then /etc
. ${tik_dir}/config
. ${TIK_CUSTOM_DIR}/config
# Check essential paths exist
if [ ! -d "${TIK_IMG_DIR}" ]; then
error "${TIK_IMG_DIR} does not exist"
fi
cleanup() {
retval=$?
log "[STOP][${retval}] $0"
if [ "${debug}" == "1" ]; then
zenity --timeout 5 --info --no-wrap --text="<b>Test Succeeded:</b>\n\nHave a nice day!"
elif [ "${retval}" == "0" ]; then
zenity --timeout 5 --info --no-wrap --title="Installation Complete!" --text="${TIK_OS_NAME} has been installed.\n\n<b>System is rebooting</b>"
systemctl reboot
else
zenity --error --no-wrap --title="Installation Failed" --text="Please file a bug report at <tt>${TIK_BUG_URL}</tt>\n\nPlease include the <tt>tik.log</tt> file\nIt can be found on the IGNITION partition on this USB Stick\n\n<b>System is shutting down</b>"
cp -a ${tik_log} /ignition
systemctl poweroff
fi
}
trap cleanup EXIT
load_modules "pre"
load_modules "pre" "custom"
get_disk
get_img
dump_image "${TIK_INSTALL_IMAGE}" "${TIK_INSTALL_DEVICE}"
load_modules "post"
load_modules "post" "custom"
set_boot_target
07070100000008000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001200000000tik-1.1.9/usr/lib07070100000009000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001600000000tik-1.1.9/usr/lib/tik0707010000000A000081A40000000000000000000000016672CAA800000359000000000000000000000000000000000000001D00000000tik-1.1.9/usr/lib/tik/config# Directory for users to add custom configuration and modules
# Default: "/etc/tik"
TIK_CUSTOM_DIR="/etc/tik"
# Directory for OS images to be deployed
# Default: "/usr/lib/tik/img"
TIK_IMG_DIR="/usr/lib/tik/img"
# To show USB devices in the install device selection dialog, uncomment this variable
# USB devices are filtered out by default
#TIK_ALLOW_USB_INSTALL_DEVICES=1
# For unattended installations the disk device to deploy the image must be defined
# Default: Undefined
#TIK_INSTALL_DEVICE=""
# For unattended installations the disk image to deploy must be defined if more than one is present
# Default: Undefined
#TIK_INSTALL_IMAGE=""
# Display name of the OS to be deployed by tik
# Default: Undefined
#TIK_OS_NAME=""
# URL for bug reports to go to
# Default: https://aeondesktop.org/reportbug
TIK_BUG_URL="https://aeondesktop.org/reportbug"
0707010000000B000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001A00000000tik-1.1.9/usr/lib/tik/lib0707010000000C000081A40000000000000000000000016672CAA800002E48000000000000000000000000000000000000002800000000tik-1.1.9/usr/lib/tik/lib/tik-functions# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2023-2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2023-2024 Richard Brown
log(){
echo "[${tik_module}][$(date +"%Y%m%d-%T")][LOG] $*" 1>&2
}
warn() {
echo "[${tik_module}][$(date +"%Y%m%d-%T")][WARN] $*" 1>&2
d --warning --text="$*"
}
error() {
echo "[${tik_module}][$(date +"%Y%m%d-%T")][ERROR] $*" 1>&2
d --error --text "$*"
exit 1
}
d(){
while true
do
retval=0
result="$(zenity "$@")" || retval=$?
log "[zenity][${retval}][${result}] $@"
case $retval in
0)
return 0
;;
1|255)
zenity --question --text="Do you really want to quit?" && exit 1
;;
esac
done
}
# variant of privileged run (prun) function that doesn't require the pkexec call to return 0
prun-opt() {
if [ "${debug}" == "1" ]; then
log "[pkexec-noexec] $@"
else
retval=0
pkexec "$@"
retval=$?
log "[pkexec][${retval}] $@"
fi
}
# Most commonly used prun function, which requires the called command to work
prun() {
prun-opt "$@"
if [ "${retval}" != "0" ]; then
error "Command <tt>$@</tt> FAILED"
fi
}
get_persistent_device_from_unix_node() {
local unix_device=$1
local schema=$2
local node
local persistent_name
node=$(basename "${unix_device}")
for persistent_name in /dev/disk/"${schema}"/*; do
if [ "$(basename "$(readlink "${persistent_name}")")" = "${node}" ];then
if [[ ${persistent_name} =~ ^/dev/disk/"${schema}"/nvme-eui ]]; then
# Filter out nvme-eui nodes as they are not descriptive to the user
continue
fi
echo "${persistent_name}"
return
fi
done
warn "Could not find <tt>${schema}</tt> representation of <tt>${node}</tt>. Using original device <tt>${unix_device}</tt>"
echo "${unix_device}"
}
get_disk() {
# Volume label for the tik install media must be set to "TIKINSTALL" to filter it out from the device list
tik_volid="TIKINSTALL"
local disk_id="by-id"
local disk_size
local disk_device
local disk_device_by_id
local disk_meta
local disk_list
local device_array
local list_items
local blk_opts="-p -n -r -o NAME,SIZE,TYPE"
local message
local blk_opts_plus_label="${blk_opts},LABEL"
local tik_install_disk_part
local part_meta
local part_count
local part_size
local part_info
local part_fs
local blk_opts_part_info="${blk_opts_plus_label},FSTYPE"
local usb_match_1="usb"
local usb_match_2=":0"
tik_install_disk_part=$(
eval lsblk "${blk_opts_plus_label}" | \
tr -s ' ' ":" | \
grep ":${tik_volid}" | \
cut -f1 -d:
)
for disk_meta in $(
eval lsblk "${blk_opts}" | grep -E "disk|raid" | tr ' ' ":"
);do
disk_size=$(echo "${disk_meta}" | cut -f2 -d:)
if [[ "${disk_size}" == "0B" ]]; then
# ignore disks with no size, e.g. empty SD card readers
continue
fi
disk_device="$(echo "${disk_meta}" | cut -f1 -d:)"
# find partitions and info for this disk
part_count=0
part_info=""
for part_meta in $(
eval lsblk "${blk_opts_part_info}" | grep -E "${disk_device}.+part.+" | tr ' ' ":"
);do
part_count=$(expr $part_count + 1)
part_size=$(echo "${part_meta}" | cut -f2 -d:)
part_fs=$(echo "${part_meta}" | cut -f5 -d:)
if [ -n "${part_info}" ]; then
part_info="${part_info},"
fi
if [ -n "${part_fs}" ]; then
part_info="${part_info}${part_fs}(${part_size})"
else
part_info="${part_info}unknown(${part_size})"
fi
done
if [[ ${part_count} -eq 0 ]]; then
part_info="none"
fi
if [[ "${tik_install_disk_part}" == "${disk_device}"* ]]; then
# ignore install source device
continue
fi
if [[ ${disk_device} =~ ^/dev/fd ]];then
# ignore floppy disk devices
continue
fi
if [[ ${disk_device} =~ ^/dev/zram ]];then
# ignore zram devices
continue
fi
disk_device_by_id=$(
get_persistent_device_from_unix_node "${disk_device}" "${disk_id}"
)
if [[ ( "${TIK_ALLOW_USB_INSTALL_DEVICES}" -ne 1 ) && ( "{$disk_device_by_id}" == *"${usb_match_1}"* || "{$disk_device_by_id}" == *"${usb_match_2}"* ) ]]; then
# ignore USB devices if TIK_ALLOW_USB_INSTALL_DEVICES not set in config
continue
fi
if [ -n "${disk_device_by_id}" ];then
disk_device=${disk_device_by_id}
fi
list_items="${list_items} $(basename ${disk_device}) ${disk_size} ${part_count} ${part_info}"
disk_list="${disk_list} $(basename ${disk_device}) ${disk_size}"
done
if [ -n "${TIK_INSTALL_DEVICE}" ];then
# install device overwritten by config.
local device=${TIK_INSTALL_DEVICE}
local device_meta
local device_size
if [ ! -e "${device}" ];then
local no_dev="Given device <tt>${device}</tt> does not exist."
error "${no_dev}"
fi
if [ ! -b "${device}" ];then
local no_block_dev="Given device <tt>${device}</tt> is not a block special."
error "${no_block_dev}"
fi
device_meta=$(
eval lsblk "${blk_opts}" "${device}" |\
grep -E "disk|raid" | tr ' ' ":"
)
device_size=$(echo "${device_meta}" | cut -f2 -d:)
# this case is not shown in manual selection, threfore we don't need partition info
list_items="$(basename ${device}) ${device_size}"
disk_list="$(basename ${device}) ${device_size}"
message="tik installation device set to to: ${device}"
log "${message}"
fi
if [ -z "${list_items}" ];then
local no_device_text="No device(s) for installation found."
error "${no_device_text}"
fi
if [ -n "${disk_list}" ];then
local count=0
local device_index=0
for entry in ${disk_list};do
if [ $((count % 2)) -eq 0 ];then
device_array[${device_index}]=${entry}
device_index=$((device_index + 1))
fi
count=$((count + 1))
done
if [ "${device_index}" -eq 1 ];then
# one single disk device found, use it
# Add back full path to it
TIK_INSTALL_DEVICE="/dev/disk/${disk_id}/${device_array[0]}"
# Fallback to unix device in case by-id does not exist
# see get_persistent_device_from_unix_node, it does fallback like this.
if [ ! -e "${TIK_INSTALL_DEVICE}" ]; then
TIK_INSTALL_DEVICE="/dev/${device_array[0]}"
fi
else
# manually select from storage list
d --list --column=Disk --column=Size --column=Partitions --column=Filesystems --width=1050 --height=340 --title="Select A Disk" --text="Select the disk to install the operating system to. <b>Make sure any important documents and files have been backed up.</b>\n" ${list_items}
# Add back full path to it
TIK_INSTALL_DEVICE="/dev/disk/${disk_id}/${result}"
# Fallback to unix device in case by-id does not exist
# see get_persistent_device_from_unix_node, it does fallback like this.
if [ ! -e "${TIK_INSTALL_DEVICE}" ]; then
TIK_INSTALL_DEVICE="/dev/${result}"
fi
fi
fi
}
get_img() {
local list_items
local message
local img_meta
local img_item
local img_list
local img_array
# Images are assumed to be named to the following standard
# $ProductName.$Version.raw.xz
# Any extraneous fields may confuse tik's detection, selection and presentation of the image to the user
for img_meta in $(
eval cd $TIK_IMG_DIR && (stat --printf="%n\t%s\n" *.raw.xz | tr ' ' ":")
);do
img_filename="$(echo $img_meta | cut -f1 -d:)"
img_size="$(echo $img_meta | cut -f2 -d:)"
list_items="${list_items} ${img_filename} ${img_size}"
done
if [ -n "${TIK_INSTALL_IMAGE}" ];then
# install image overwritten by config.
local img=${TIK_INSTALL_IMAGE}
local img_meta
local img_size
if [ ! -e "${img}" ];then
local no_img="Given image <tt>${img}</tt> does not exist."
error "${no_img}"
fi
if [ ! -s "${img}" ];then
local empty_img="Given image <tt>${img}</tt> is empty."
error "${empty_img}"
fi
img_meta=$(
eval cd $TIK_IMG_DIR && (stat --printf="%n\t%s\n" $img | tr ' ' ":")
)
img_filename="$(echo $img_meta | cut -f1 -d:)"
img_size="$(echo $img_meta | cut -f2 -d:)"
list_items="${list_items} ${img_filename} ${img_size}"
message="tik installation image set to to: ${img}"
log "${message}"
fi
if [ -z "${list_items}" ];then
local no_image_text="No images(s) for installation found"
error "${no_image_text}"
fi
img_list=${list_items}
if [ -n "${img_list}" ];then
local count=0
local img_index=0
for entry in ${img_list};do
if [ $((count % 2)) -eq 0 ];then
img_array[${img_index}]=${entry}
img_index=$((img_index + 1))
fi
count=$((count + 1))
done
if [ "${img_index}" -eq 1 ];then
# one single disk image found, use it
TIK_INSTALL_IMAGE="${img_array[0]}"
else
# manually select from storage list
d --list --column=Disk --column=Size --title="Select A Image" --text="Select the operating system image to install.\n" ${list_items}
TIK_INSTALL_IMAGE="$result"
fi
fi
}
dump_image() {
local image_source_files=$1
local image_target=$2
local image_source
d --question --no-wrap --title="Begin Installation?" --text="Once the installation begins the changes to the selected disk are irreversible.\n\n<b>Proceeding will fully erase the disk.</b>\n\nContinue with installation?"
(xzcat ${TIK_IMG_DIR}/${image_source_files} | pv -f -F "# %b copied in %t %r" | prun /usr/bin/dd of=${image_target} bs=64k) 2>&1 | d --progress --title="Installing ${TIK_OS_NAME}" --pulsate --auto-close --no-cancel --width=400
prun /usr/bin/sync | d --progress --title="Syncing" --pulsate --auto-close --no-cancel --width=400
}
set_boot_target() {
if [ "${debug}" == "1" ]; then
log "[debug] Not setting EFI boot target"
else
# Cleanup any existing openSUSE boot entries
prun-opt /usr/sbin/efibootmgr -B -L "openSUSE Boot Manager"
prun /usr/sbin/efibootmgr -O
# Currently assuming Aeon-like partition layout and shim name. This function will need extra intelligence to probe partitions for other image layouts
prun /usr/sbin/efibootmgr -c -L "openSUSE Boot Manager" -d ${TIK_INSTALL_DEVICE} -l "\EFI\systemd\shim.efi" -p 2
# Log to show the resulting eficonfig
log "[efibootmgr] $(prun /usr/sbin/efibootmgr)"
fi
}
load_modules() {
local module_dir
if [[ $2 = "custom" ]]; then
module_dir=$TIK_CUSTOM_DIR/modules/$1
else
module_dir=$tik_dir/modules/$1
fi
if [ -n "$(ls -A $module_dir)" ]; then
for f in $module_dir/*
do
tik_module="$f"
log "[START] $module_dir/$f"
. $f
log "[STOP] $module_dir/$f"
done
fi
tik_module="tik"
}
0707010000000D000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000001E00000000tik-1.1.9/usr/lib/tik/modules0707010000000E000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000002300000000tik-1.1.9/usr/lib/tik/modules/post0707010000000F000081A40000000000000000000000016672CAA800000E1F000000000000000000000000000000000000002E00000000tik-1.1.9/usr/lib/tik/modules/post/10-encrypt# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2024 Richard Brown
generate_recoveryKey() {
modhex=('c' 'b' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'n' 'r' 't' 'u' 'v')
mapfile -t raw_key < <(hexdump -v --format '1/1 "%u\n"' -n 32 /dev/random)
[ "${#raw_key[@]}" = 32 ]
key=""
for ((i=0;i<"${#raw_key[@]}";++i)); do
[ "$i" -gt 0 ] && [ "$((i%4))" -eq 0 ] && key="$key-"
c="${raw_key[i]}"
key="$key${modhex[$((c>>4))]}${modhex[$((c&15))]}"
done
}
display_recoveryKey() {
log "Displaying Recovery Key"
zenity --width=500 --height=500 --no-wrap --warning --title="Encryption Recovery Key" --text="A secret recovery key has been generated for your Aeon installation:\n\n <b><big>$key</big></b>\n\nPlease save this secret recovery key at a secure location\nIt may be used to regain access to your system if the other credentials have been lost or forgotten\nThe recovery key can be used in place of a password whenever authentication is requested\n\nYou may optionally scan the recovery key off screen:\n<span face='monospace'>$(qrencode $key -t UTF8i)</span>"
log "Recovery Key Dialogue Dismissed"
}
encrypt_disk() {
probe_partitions $TIK_INSTALL_DEVICE "btrfs" "/usr/lib/os-release"
if [ -z "${probedpart}" ]; then
error "ENCRYPTION FAILED: New Installation NOT FOUND"
fi
prun /usr/bin/mkdir ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1 ${probedpart} ${mig_dir}/mnt
prun /usr/bin/systemd-repart --pretty 0 --root ${mig_dir}/mnt --dry-run=0 ${probedpart}
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/var ${probedpart} ${mig_dir}/mnt/var
prun /lib/systemd/systemd-growfs ${mig_dir}/mnt/var
prun /usr/bin/umount ${mig_dir}/mnt/var
prun /usr/sbin/btrfs filesystem resize -32m /mnt
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/sbin/cryptsetup reencrypt --force-password --encrypt --reduce-device-size 32m ${probedpart} cr_root <<<"$key"
echo '{"type":"systemd-recovery","keyslots":["0"]}' | prun /usr/sbin/cryptsetup token import "${probedpart}"
prun /usr/sbin/btrfs rescue fix-device-size /dev/mapper/cr_root
prun /usr/bin/mount -o compress=zstd:1 /dev/mapper/cr_root ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/var /dev/mapper/cr_root ${mig_dir}/mnt/var
etcmountcmd=$(cat ${mig_dir}/mnt/etc/fstab | grep "overlay /etc" | sed 's/\/sysroot\//${mig_dir}\/mnt\//g' | sed 's/\/work-etc.*/\/work-etc ${mig_dir}\/mnt\/etc\//' | sed 's/overlay \/etc overlay/\/usr\/bin\/mount -t overlay overlay -o/')
eval prun "$etcmountcmd"
echo "cr_root ${probedpart} none x-initrd.attach" | prun tee ${mig_dir}/mnt/etc/crypttab
probe_partitions $TIK_INSTALL_DEVICE "vfat" "/EFI/systemd/shim.efi"
prun /usr/bin/mount ${probedpart} ${mig_dir}/mnt/boot/efi
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/.snapshots /dev/mapper/cr_root ${mig_dir}/mnt/.snapshots
prun /usr/bin/mount -t tmpfs -o size=10m tmpfs "${mig_dir}/mnt/run"
prun /usr/bin/mount -t tmpfs -o size=10m tmpfs "${mig_dir}/mnt/tmp"
for i in proc dev sys; do
prun /usr/bin/mount --bind "/$i" "${mig_dir}/mnt/$i"
done
prun /usr/bin/chroot ${mig_dir}/mnt <<EOT
sdbootutil mkinitrd
umount /etc
EOT
for i in proc dev sys run tmp 'boot/efi' etc var '.snapshots'; do
prun /usr/bin/umount "${mig_dir}/mnt/$i"
done
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/bin/rmdir ${mig_dir}/mnt
}
generate_recoveryKey
display_recoveryKey
encrypt_disk07070100000010000081A40000000000000000000000016672CAA800001118000000000000000000000000000000000000002A00000000tik-1.1.9/usr/lib/tik/modules/post/20-mig# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2024 Richard Brown
writemigdesktop() {
prun-opt /usr/bin/cat >> $1/.config/autostart/aeon-mig-firstboot.desktop << "EOF"
[Desktop Entry]
Name=Aeon Migration FirstBoot Setup
Comment=Sets up Aeon Correctly On FirstBoot after Migration
Exec=/usr/bin/aeon-mig-firstboot
Icon=org.gnome.Terminal
Type=Application
Categories=Utility;System;
Name[en_GB]=startup
EOF
prun-opt /usr/bin/chmod 666 $1/.config/autostart/aeon-mig-firstboot.desktop
}
if [ "${migrate}" == 1 ]; then
probe_partitions $TIK_INSTALL_DEVICE "btrfs" "/usr/lib/os-release"
if [ -z "${probedpart}" ]; then
error "MIGRATION FAILED: New Installation NOT FOUND"
fi
prun /usr/bin/mkdir ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1 ${probedpart} ${mig_dir}/mnt
prun /usr/bin/systemd-repart --pretty 0 --root ${mig_dir}/mnt --dry-run=0 ${probedpart}
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/var ${probedpart} ${mig_dir}/mnt/var
prun /lib/systemd/systemd-growfs ${mig_dir}/mnt/var
etcmountcmd=$(cat ${mig_dir}/mnt/etc/fstab | grep "overlay /etc" | sed 's/\/sysroot\//${mig_dir}\/mnt\//g' | sed 's/\/work-etc.*/\/work-etc ${mig_dir}\/mnt\/etc\//' | sed 's/overlay \/etc overlay/\/usr\/bin\/mount -t overlay overlay -o/')
eval prun "$etcmountcmd"
prun /usr/bin/cat ${mig_dir}/passwd.out | prun tee -a ${mig_dir}/mnt/etc/passwd
prun /usr/bin/cat ${mig_dir}/group.out | prun tee -a ${mig_dir}/mnt/etc/group
prun /usr/bin/cat ${mig_dir}/shadow.out | prun tee -a ${mig_dir}/mnt/etc/shadow
prun /usr/bin/sed -i "/^wheel:/ s/$/$(head -n 1 ${mig_dir}/passwd.out | awk -F'[/:]' '{print $1}')/" ${mig_dir}/mnt/etc/group
prun /usr/bin/cp -a ${mig_dir}/subuid ${mig_dir}/mnt/etc/subuid
prun /usr/bin/cp -a ${mig_dir}/subgid ${mig_dir}/mnt/etc/subgid
# It's not guaranteed that the system will have existing network configs, localtime or AccountsService
prun-opt /usr/bin/cp -a ${mig_dir}/system-connections/* ${mig_dir}/mnt/etc/NetworkManager/system-connections
prun-opt /usr/bin/cp -a ${mig_dir}/localtime ${mig_dir}/mnt/etc/localtime
prun-opt /usr/bin/cp -a ${mig_dir}/users/* ${mig_dir}/mnt/var/lib/AccountsService/users
prun-opt /usr/bin/cp -a ${mig_dir}/icons/* ${mig_dir}/mnt/var/lib/AccountsService/icons
prun-opt /usr/bin/cp -a ${mig_dir}/bluetooth/* ${mig_dir}/mnt/var/lib/bluetooth
prun-opt /usr/bin/cp -a ${mig_dir}/fprint/* ${mig_dir}/mnt/var/lib/fprint
prun-opt /usr/bin/cp -a ${mig_dir}/openvpn/* ${mig_dir}/mnt/etc/openvpn
prun /usr/bin/umount ${mig_dir}/mnt/etc
prun /usr/bin/umount ${mig_dir}/mnt/var
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1,subvol=/@ ${probedpart} ${mig_dir}/mnt
prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/home
(prun /usr/sbin/btrfs send ${mig_dir}/${snap_dir} | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}/mnt) 2>&1 | d --progress --title="Restoring /home" --pulsate --auto-close --no-cancel --width=400
prun /usr/bin/mv ${mig_dir}/mnt/${snap_dir} ${mig_dir}/mnt/home
prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/mnt/home ro false
for subsubvol in $(prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/${snap_dir} --sort=path | rev | cut -f1 -d' ' | rev | sed 's/^@//'); do
subsubvolname=$(basename $subsubvol)
subsubdirname=$(dirname $subsubvol | awk -F "${mig_dir}/${snap_dir}" '{print $2}')
(prun /usr/sbin/btrfs send ${subsubvol} | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}/mnt/home/${subsubdirname} ) 2>&1 | d --progress --title="Restoring containers" --pulsate --auto-close --no-cancel --width=400
prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/mnt/home/${subsubdirname}/${subsubvolname} ro false
prun-opt /usr/bin/sed -i 's/driver = "overlay"/driver = "btrfs"/g' ${mig_dir}/mnt/etc/containers/storage.conf
done
for userhome in ${mig_dir}/mnt/home/*/; do
writemigdesktop $userhome
done
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/bin/rmdir ${mig_dir}/mnt
fi07070100000011000041ED0000000000000000000000026672CAA800000000000000000000000000000000000000000000002200000000tik-1.1.9/usr/lib/tik/modules/pre07070100000012000081A40000000000000000000000016672CAA800000887000000000000000000000000000000000000002D00000000tik-1.1.9/usr/lib/tik/modules/pre/10-welcome# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2024 Richard Brown
# SPDX-FileCopyrightText: Copyright 2024 Raymond Yip
proceedInstall() {
d --info --ok-label="Install Now" --no-wrap --width=300 --height=300 --icon=distributor-logo-Aeon-symbolic --title="" --text="<big>Welcome to ${TIK_OS_NAME}</big>\n\nPlease press <b>Install Now</b> to continue"
}
displayACWarningMsg() {
d --warning --no-wrap --title="AC Power Recommended" --text="Runnning on battery power detected\n\nIt is recommended to connect the system to AC power during the install"
}
checkLaptop() {
chassis=`cat /sys/class/dmi/id/chassis_type`
#Test for respectively Handheld, Notebook, Laptop, and Portable
#if chassis variable matches 8 9 10 or 11 function continues else it proceeds to test AC power and Battery
[[ "$chassis" =~ ^(8|9|10|11)$ ]] || return
#Tested machine is confirmed mobile
givePowerRecommendation=false
#Only check for AC and Battery power connections with upower
updevices=`/usr/bin/upower -e|grep -E 'AC|BAT'`
for pdev in $updevices; do
#Get detailed info for each AC and BAT device in upower
upinfo=`/usr/bin/upower -i $pdev|grep -E 'online|state'`
#Check for discharging state or AC power offline which is equal to no state
if [[ "$upinfo" =~ (discharging|no) ]]; then
#Give power recommendation only once, so set this to true
givePowerRecommendation=true
fi
done
if [ "$givePowerRecommendation" = true ]; then
log "AC Power disconnected and Battery is not charging"
displayACWarningMsg
fi
}
verify_efi() {
# Verify that the system was booted with EFI, exit with error if not
if [ ! -d /sys/firmware/efi ]; then
# System was not booted with EFI
local error_msg="openSUSE Aeon requires UEFI mode, which is not found on your system.\nPlease check your BIOS settings to see if UEFI can be enabled."
error "${error_msg}"
fi
}
proceedInstall
verify_efi
checkLaptop
07070100000013000081A40000000000000000000000016672CAA800002FF0000000000000000000000000000000000000002900000000tik-1.1.9/usr/lib/tik/modules/pre/20-mig# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2024 Richard Brown
mig_dir=/var/lib/tik/mig
snap_dir=homebk
if [ ! -d ${mig_dir} ]; then
prun /usr/bin/mkdir -p ${mig_dir}
fi
probe_partitions() {
local filesystem_type=$2
local filematch=$3
local device=$1
local mountops
local part
if [[ "${filesystem_type}" == "btrfs" ]]; then
mountops="-o compress=zstd:1"
fi
prun /usr/bin/mkdir -p ${mig_dir}/mnt
probedpart=""
for part in $(lsblk ${device} -p -n -r -o ID-LINK,FSTYPE|tr -s ' ' ";"|grep ";${filesystem_type}"|cut -d\; -f1); do
# Fallback to unix device in order to fix issue with USB devices
prun /usr/bin/mount ${mountops} "$(/usr/bin/readlink -f "/dev/disk/by-id/${part}")" "${mig_dir}/mnt"
# Check if ${filematch} exists
if [ -f ${mig_dir}/mnt/${filematch} ]; then
# Fallback to unix device in order to fix issue USB devices
probedpart="$(/usr/bin/readlink -f "/dev/disk/by-id/""${part}")"
log "[probe_partitions] /dev/disk/by-id/${part} found"
if grep -q 'PRETTY_NAME="openSUSE MicroOS"' ${mig_dir}/mnt/${filematch} && [ -f ${mig_dir}/mnt/usr/bin/gnome-shell ]; then
# Found legacy Aeon, activate easter egg
log "Legacy Aeon Install FOUND"
legacy_aeon=1
fi
fi
prun-opt /usr/bin/umount ${mig_dir}/mnt
done
prun /usr/bin/rmdir ${mig_dir}/mnt
}
if [ ! -z "$(ls -A ${mig_dir})" ]; then
log "existing backup found"
zenity --question --no-wrap --cancel-label="No, Delete Backup" --title="Existing user backup detected" --text="These users can be restored to the new installation\n\nWould you like to use this backup?"
oldbackupyn=$?
log "[oldbackupyn][${oldbackupyn}]"
if [ "${oldbackupyn}" == 0 ]; then
skipbackup=1
migrate=1
log "backup skipped, migration will use existing backup"
else
prun-opt /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro false
for subsubvol in $(prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/${snap_dir} --sort=path | rev | cut -f1 -d' ' | rev | sed "s/^@//"); do
prun /usr/sbin/btrfs subvolume delete ${subsubvol}
done
prun-opt /usr/sbin/btrfs subvolume delete ${mig_dir}/${snap_dir}
prun-opt /usr/bin/rm ${mig_dir}/*.out
prun-opt /usr/bin/rm ${mig_dir}/system-connections/*
prun-opt /usr/bin/rmdir ${mig_dir}/system-connections
prun-opt /usr/bin/rm ${mig_dir}/users/*
prun-opt /usr/bin/rmdir ${mig_dir}/users
prun-opt /usr/bin/rm ${mig_dir}/icons/*
prun-opt /usr/bin/rmdir ${mig_dir}/icons
prun-opt /usr/bin/rm ${mig_dir}/localtime
prun-opt /usr/bin/rm ${mig_dir}/subgid
prun-opt /usr/bin/rm ${mig_dir}/subuid
prun-opt /usr/bin/rm ${mig_dir}/bluetooth/*
prun-opt /usr/bin/rmdir ${mig_dir}/bluetooth
prun-opt /usr/bin/rm ${mig_dir}/openvpn/*
prun-opt /usr/bin/rmdir ${mig_dir}/openvpn
prun-opt /usr/bin/rm -R ${mig_dir}/fprint/*
prun-opt /usr/bin/rmdir ${mig_dir}/fprint
prun-opt /usr/bin/rmdir ${mig_dir}/mnt
fi
fi
get_disk
if [ -z "${skipbackup}" ]; then
# Although Legacy Aeon didn't officially support LUKS encrypted installations,
# some users might have nevertheless enabled encryption anyway.
# Search for existing crypto_LUKS partitions and, if found, prompt the user
# to unlock those so that the migration module can find existing data.
for encrypted_partition in $(lsblk ${TIK_INSTALL_DEVICE} -p -n -r -o ID-LINK,FSTYPE|tr -s ' ' ";"|grep ";crypto_LUKS"|cut -d\; -f1); do
if [ -e /dev/mapper/crypt_${encrypted_partition} ]; then
# Already opened for some reason... do not prompt for the passphrase
# but ensure we will clean up afterwards
crypt_opened="${crypt_opened} crypt_${encrypted_partition}"
else
while [ 1 ]; do
passphrase=$(zenity --password --title="Encrypted partition (${encrypted_partition}) detected" --cancel-label="Skip") || break
if [ -n "${passphrase}" ]; then
echo -n "${passphrase}" | prun /usr/sbin/cryptsetup luksOpen /dev/disk/by-id/${encrypted_partition} crypt_${encrypted_partition}
if [ "${?}" -eq 0 ]; then
crypt_opened="${crypt_opened} crypt_${encrypted_partition}"
# Wait for the mapped device to appear
wait_count=0
while [ ! -e /dev/mapper/crypt_${encrypted_partition} ] && [ ${wait_count} -lt 5 ]; do
sleep 1
wait_count=$((wait_count + 1))
done
break
fi
fi
done
fi
done
unset passphrase
# Probe selected disk for a btrfs partition containing /usr/lib/os-release
probe_partitions $TIK_INSTALL_DEVICE "btrfs" "/usr/lib/os-release"
if [ -n "${probedpart}" ]; then
prun /usr/bin/mkdir ${mig_dir}/mnt
if prun /usr/bin/mount -o compress=zstd:1,subvol=/@/home ${probedpart} ${mig_dir}/mnt; then
prun /usr/sbin/btrfs quota rescan -w ${mig_dir}/mnt | d --progress --title="Detected existing /home subvolume.." --pulsate --auto-close --no-cancel --width=400
home_size=$(prun /usr/sbin/btrfs qgroup show --raw -f ${mig_dir}/mnt | grep @/home$ | awk '{print $2}')
tik_stick_size=$(prun /usr/sbin/btrfs fi usage --raw ${mig_dir} | grep estimated | awk '{print $3}')
if [ ${home_size} -gt ${tik_stick_size} ]; then
# Not enough space to offer migration
migrate=0
fi
if [ ${home_size} -le 16384 ]; then
# /home subvolume is empty
migrate=0
fi
prun /usr/bin/umount ${mig_dir}/mnt
else
log "no @/home subvolume found on ${probedpart}"
migrate=0
fi
prun /usr/bin/rmdir ${mig_dir}/mnt
# partition found, /home subvolume found, no known reason to not migrate, so ask the user
if [ -z "${migrate}" ]; then
if [ "${legacy_aeon}" == 1 ]; then
d --info --width=300 --height=300 --icon=distributor-logo-Aeon-symbolic --no-wrap --title="Message from the Aeon Team" --text="We'd like to thank you for adopting openSUSE Aeon so early in it's development,\nbefore we fully understood what we were building or how we wanted it to look\n\nWe are sorry that you need to reinstall your system\n\nThank you so much for your support.\nWe hope you enjoy the new look openSUSE Aeon"
fi
zenity --question --no-wrap --title="Backup users from the existing install?" --text="These users will be restored to the new installation."
migrateyn=$?
if [ "${migrateyn}" == 0 ]; then
migrate=1
else
migrate=0
fi
fi
fi
if [ "${migrate}" == 1 ]; then
# We're migrating, lets go!
prun /usr/bin/mkdir ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/home ${probedpart} ${mig_dir}/mnt
# Check for existing snapshot from interrupted backup and delete if it exists boo#1224824
if [ -d ${mig_dir}/mnt/${snap_dir} ]; then
prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/${snap_dir}
fi
prun /usr/sbin/btrfs subvolume snapshot -r ${mig_dir}/mnt ${mig_dir}/mnt/${snap_dir}
(prun /usr/sbin/btrfs send ${mig_dir}/mnt/${snap_dir} | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}) 2>&1 | d --progress --title="Backing up /home" --pulsate --auto-close --no-cancel --width=400
prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/${snap_dir}
# Probe for subvolumes nested beneath /home and back them up also
if (prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/mnt | grep -q "ID "); then
prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro false
for subsubvol in $(prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/mnt --sort=path | rev | cut -f1 -d' ' | rev | sed 's/^@\/home//'); do
subsubvolname=$(basename $subsubvol)
subsubdirname=$(dirname $subsubvol)
prun /usr/sbin/btrfs subvolume snapshot -r ${mig_dir}/mnt/${subsubvol} ${mig_dir}/mnt/${subsubvolname}
(prun /usr/sbin/btrfs send ${mig_dir}/mnt/${subsubvolname} | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}/${snap_dir}/${subsubdirname}) 2>&1 | d --progress --title="Backing up containers" --pulsate --auto-close --no-cancel --width=400
prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/${subsubvolname}
done
prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro true
fi
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1 ${probedpart} ${mig_dir}/mnt
prun /usr/bin/mount -o compress=zstd:1,subvol=/@/var ${probedpart} ${mig_dir}/mnt/var
etcmntcmd=$(cat ${mig_dir}/mnt/etc/fstab | grep "overlay /etc" | sed 's/\/sysroot\//${mig_dir}\/mnt\//g' | sed 's/\/work-etc.*/\/work-etc ${mig_dir}\/mnt\/etc\//' | sed 's/overlay \/etc overlay/\/usr\/bin\/mount -t overlay overlay -o/')
eval prun "$etcmntcmd"
prun /usr/bin/awk -F'[/:]' '($3 >= 1000 && $3 != 65534)' ${mig_dir}/mnt/etc/passwd | prun /usr/bin/awk -F':' '{ $7="/bin/bash"; print };' OFS=':' | prun tee ${mig_dir}/passwd.out
prun /usr/bin/awk -F'[/:]' '($3 >= 1000 && $3 != 65534 && $3 != 65533)' ${mig_dir}/mnt/etc/group | prun tee ${mig_dir}/group.out
prun /usr/bin/awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' ${mig_dir}/mnt/etc/passwd | prun /usr/bin/grep -f - ${mig_dir}/mnt/etc/shadow | prun tee ${mig_dir}/shadow.out
prun /usr/bin/cp -a ${mig_dir}/mnt/etc/subuid ${mig_dir}/subuid
prun /usr/bin/cp -a ${mig_dir}/mnt/etc/subgid ${mig_dir}/subgid
# It's not guaranteed that the system will have existing network configs, custom localtime or AccountsService
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/NetworkManager/system-connections ${mig_dir}/system-connections
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/localtime ${mig_dir}/localtime
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/AccountsService/users ${mig_dir}/users
prun-opt /usr/bin/chmod 744 ${mig_dir}/users
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/AccountsService/icons ${mig_dir}/icons
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/bluetooth ${mig_dir}/bluetooth
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/fprint ${mig_dir}/fprint
prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/openvpn ${mig_dir}/openvpn
prun-opt /usr/bin/umount ${mig_dir}/mnt/etc
prun /usr/bin/umount ${mig_dir}/mnt/var
prun /usr/bin/umount ${mig_dir}/mnt
prun /usr/bin/rmdir ${mig_dir}/mnt
fi
# Close eventual mapped LUKS devices
if [ -n "${crypt_opened}" ]; then
for mapped_partition in ${crypt_opened}; do
if [ -e /dev/mapper/crypt_${encrypted_partition} ]; then
# We are going to replace the encrypted partition anyway, so if
# we're unable to gracefully close the device after 5 seconds,
# just give up (hence the prun-opt usage)
wait_count=0
while ! prun-opt /usr/sbin/cryptsetup luksClose /dev/mapper/${mapped_partition} && [ ${wait_count} -lt 5 ]; do
sleep 1
wait_count=$((wait_count + 1))
done
fi
done
fi
fi
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!89 blocks