From a58921681f923d116c4741527d43ad1e2b926762 Mon Sep 17 00:00:00 2001 From: Fierelier Date: Sat, 28 Jan 2023 01:50:19 +0100 Subject: [PATCH] Replace live-installer with a more complex Python script --- mods/live-installer/data/bin/login | 195 +--------- .../data/opt/wdvn/installer/main | 347 ++++++++++++++++++ mods/live-installer/modscript | 4 +- 3 files changed, 351 insertions(+), 195 deletions(-) create mode 100755 mods/live-installer/data/opt/wdvn/installer/main diff --git a/mods/live-installer/data/bin/login b/mods/live-installer/data/bin/login index 428fae9..fc0e7dd 100755 --- a/mods/live-installer/data/bin/login +++ b/mods/live-installer/data/bin/login @@ -38,7 +38,7 @@ clear while true; do echo "" echo "Welcome to windvn!" - echo "1: Fast install" + echo "1: Install" echo "2: Open bash" echo "3: Reboot" echo "4: Shut down" @@ -46,198 +46,7 @@ while true; do echo "" if [ "$CHOICE" == "1" ]; then - ( - set -e - YN="n" - while [ "$YN" == "n" ]; do - echo "" - lsblk -d -o PATH,SIZE - read -p "Device: " DEVICE - echo "" - lsblk "$DEVICE" -o NAME,SIZE,FSTYPE,PARTLABEL - read -p "All data on this disk will be erased! Continue? [y,n]: " YN - YN="$(echo "$YN" | tr "[:upper:]" "[:lower:]")" - if [ "$YN" != "y" ]; then - YN="n" - fi - done - - # Ask for encryption - WDVN_ENCRYPT="" - WDVN_ENCRYPT_PASS="" - while true; do - read -p "Encrypt the disk? [y,n]: " WDVN_ENCRYPT - WDVN_ENCRYPT="$(echo "$WDVN_ENCRYPT" | tr "[:upper:]" "[:lower:]")" - if [ "$WDVN_ENCRYPT" == "y" ]; then - apt -y install cryptsetup - echo "" - loadkeys us - while true; do - read -s -p "Passphrase: " WDVN_ENCRYPT_PASS - echo "" - read -s -p "Confirm passphrase: " WDVN_ENCRYPT_PASS_CONFIRM - echo "" - if [ "$WDVN_ENCRYPT_PASS" == "$WDVN_ENCRYPT_PASS_CONFIRM" ]; then - break - fi - echo "Passwords don't match." - echo "" - done - service console-setup.sh restart - udevadm trigger --subsystem-match=input --action=change - service keyboard-setup.sh restart - break - fi - - if [ "$WDVN_ENCRYPT" == "n" ]; then - break - fi - done - - # Create partitions - echo "Creating partitions ..." - wipefs --all "$DEVICE" - sgdisk -n 1:2048:+1M -c 1:"BIOS boot partition" -t 1:ef02 "$DEVICE" - sgdisk -n 2::+512M -c 2:"EFI System" -t 2:ef00 "$DEVICE" - sgdisk -n 3::-0 -c 3:"Linux filesystem" -t 3:8300 "$DEVICE" - sgdisk --hybrid=1:2:3 "$DEVICE" - PART_EFI="$(echo "${DEVICE}"*2)" - PART_DATA="$(echo "${DEVICE}"*3)" - DEV_DATA="$PART_DATA" - - # Additional passphrases - if [ "$WDVN_ENCRYPT" == "y" ]; then - echo "$WDVN_ENCRYPT_PASS" | cryptsetup luksFormat --type luks1 "$PART_DATA" - - while true; do - echo "" - read -p "Add another passphrase? [y,n]: " CHOICE - CHOICE="$(echo "$CHOICE" | tr "[:upper:]" "[:lower:]")" - if [ "$CHOICE" == "y" ]; then - loadkeys us - while true; do - read -s -p "Passphrase: " WDVN_ENCRYPT_PASS_ADD - echo "" - read -s -p "Confirm passphrase: " WDVN_ENCRYPT_PASS_ADD_CONFIRM - echo "" - if [ "$WDVN_ENCRYPT_PASS_ADD" == "$WDVN_ENCRYPT_PASS_ADD_CONFIRM" ]; then - echo "$WDVN_ENCRYPT_PASS -$WDVN_ENCRYPT_PASS_ADD" | cryptsetup luksAddKey "$PART_DEV" - break - fi - echo "Passwords don't match." - echo "" - done - service console-setup.sh restart - udevadm trigger --subsystem-match=input --action=change - service keyboard-setup.sh restart - fi - - if [ "$CHOICE" == "n" ]; then - break - fi - done - - echo "$WDVN_ENCRYPT_PASS" | cryptsetup luksOpen "$PART_DATA" system - - PART_DATA="/dev/mapper/system" - fi - - # Format partitions - echo "Formatting partitions ..." - mkfs.fat -F32 "$PART_EFI" - mkfs.ext4 "$PART_DATA" - - # Mount target partition - echo "Mounting partitions ..." - mkdir -p "/media/install" - mount "$PART_DATA" "/media/install" - mkdir -p "/media/install/efi" - mount "$PART_EFI" "/media/install/efi" - - # Creating swap - echo "Creating swap ..." - dd if=/dev/zero of="/media/install/swap" bs=1M count=512 status=progress - chmod 600 "/media/install/swap" - mkswap "/media/install/swap" - swapon "/media/install/swap" - - # Add files - echo "Adding files ..." - unsquashfs -f -d "/media/install" "/lib/live/mount/medium/live/filesystem.squashfs" - - if [ "$WDVN_ENCRYPT" == "y" ]; then - echo "GRUB_ENABLE_CRYPTODISK=y" > "/media/install/etc/default/grub.d/cryptodisk.cfg" - fi - - # Set hostname - echo "Setting hostname ..." - echo "$(head -c4 "/media/install/etc/hostname" - - # Write fstab - UUID_PART_DATA="$(blkid -o value -s UUID "$PART_DATA")" - UUID_DEV_DATA="$(blkid -o value -s UUID "$DEV_DATA")" - - echo "Writing fstab ..." - if [ "$WDVN_ENCRYPT" == "y" ]; then - echo "GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX cryptdevice=UUID=$UUID_DEV_DATA root=UUID=$UUID_PART_DATA\"" >> "/media/install/etc/default/grub.d/cryptodisk.cfg" - fi - - if [ "$WDVN_ENCRYPT" == "y" ]; then - echo "system UUID=$UUID_DEV_DATA none luks" >"media/install/etc/crypttab" - fi - echo "UUID=$UUID_PART_DATA / ext4 errors=remount-ro 0 1" >>"/media/install/etc/fstab" - echo "/swap none swap sw 0 0" >>"/media/install/etc/fstab" - - # Copy keyboard settings - echo "Copying keyboard settings ..." - mkdir -p "/media/install/etc/default" - cp "/etc/default/keyboard" "/media/install/etc/default/keyboard" - - # Remove live-specific packages - echo "Removing live-specific packages ..." - wdvn-chroot "/media/install" apt -y remove live-boot live-boot-initramfs-tools - wdvn-chroot "/media/install" apt -y autoremove - if [ "$WDVN_ENCRYPT" == "y" ]; then - wdvn-chroot "/media/install" apt -y install cryptsetup-initramfs - else - wdvn-chroot "/media/install" update-initramfs -u - fi - rm "/media/install/bin/login" - mv "/media/install/bin/login.oobe" "/media/install/bin/login" - - # Install GRUB - echo "Installing grub ..." - wdvn-chroot "/media/install" grub-install --target=i386-efi --uefi-secure-boot --efi-directory="/efi" --boot-directory="/boot" "$DEVICE" - wdvn-chroot "/media/install" grub-install --target=x86_64-efi --uefi-secure-boot --efi-directory="/efi" --boot-directory="/boot" "$DEVICE" - wdvn-chroot "/media/install" grub-install --target=i386-pc --boot-directory="/boot" "$DEVICE" - wdvn-chroot "/media/install" update-grub - - # Unmount - echo "Unmounting ..." - swapoff "/media/install/swap" - umount -l "/media/install/efi" - rmdir "/media/install/efi" - umount -l "/media/install" - rmdir "/media/install" - if [ "$WDVN_ENCRYPT" == "y" ]; then - cryptsetup luksClose system - fi - - echo "" - echo Success. Press ENTER to quit setup. - read - ) - if [ "$?" != "0" ]; then - echo "ERROR. Cleaning up ..." - swapoff "/media/install/swap" - umount -l "/media/install/efi" - umount -l "/media/install" - cryptsetup luksClose system - echo "" - echo An error occured. Press ENTER to quit setup. - read - fi + /opt/wdvn/installer/main fi if [ "$CHOICE" == "2" ]; then diff --git a/mods/live-installer/data/opt/wdvn/installer/main b/mods/live-installer/data/opt/wdvn/installer/main new file mode 100755 index 0000000..d3324c5 --- /dev/null +++ b/mods/live-installer/data/opt/wdvn/installer/main @@ -0,0 +1,347 @@ +#!/usr/bin/python3 +import os +import subprocess +import getpass +import time +import shutil +import random + +def nerr(func,*args,**kwargs): + try: + return func(*args,**kwargs) + except: + return + +def choiceYn(question,defaultPick = None): + qstring = "\n" + question + " y/n" + if defaultPick != None: qstring = qstring + " [" +defaultPick+ "]" + qstring = qstring + ": " + while True: + chinput = input(qstring) + if chinput == "" and defaultPick != None: + chinput = defaultPick + chinput = chinput.lower() + if chinput == "y": return True + if chinput == "n": return False + +def choice(question,options,defaultPick = None,direction = 1): + qstring = "\n" + for option in options: + qstring = qstring + "- " + option + "\n" + qstring = qstring + question + if defaultPick != None: qstring = qstring + " [" +defaultPick+ "]" + qstring = qstring + ": " + + while True: + chinput = input(qstring) + if chinput == "" and defaultPick != None: + chinput = defaultPick + if chinput in options: return chinput + +def choiceInput(question,defaultPick = None): + qstring = "\n" + question + if defaultPick != None: qstring = qstring + " [" +defaultPick+ "]" + qstring = qstring + ": " + + while True: + chinput = input(qstring) + if chinput == "": + if defaultPick == None: continue + return defaultPick + return chinput + +def choicePass(question): + while True: + print("") + passw = getpass.getpass(question+ ": ") + passwConfirm = getpass.getpass(question+ " (repeat): ") + if passw == passwConfirm: return passw + print("Passwords don't match, try again.") + +def checkProc(proc): + rtn = proc.wait() + if rtn != 0: raise Exception("Process returned error: " +str(rtn)) + +def call(*args,**kwargs): + proc = subprocess.Popen(*args,**kwargs) + checkProc(proc) + return + +def callString(*args,**kwargs): + proc = subprocess.Popen(*args,**kwargs,stdout=subprocess.PIPE) + output = proc.stdout.read().decode("utf-8").strip("\n") + checkProc(proc) + return output + +def callList(*args,**kwargs): + proc = subprocess.Popen(*args,**kwargs,stdout=subprocess.PIPE) + output = proc.stdout.read().decode("utf-8").strip("\n").split("\n") + checkProc(proc) + return output + +def getDisks(): + return callList(["lsblk","-ndo","PATH"]) + +def getPartitions(): + disks = getDisks() + partitions = callList(["lsblk","-no","PATH"]) + index = 0 + length = len(partitions) + while index < length: + if partitions[index] in disks: + del partitions[index] + length -= 1 + continue + index += 1 + return partitions + +def getDiskType(disk): + return callString(["blkid","-o","value","-s","PTTYPE",disk]) + +def getPartitionType(partition): + return callString(["blkid","-o","value","-s","TYPE",partition]) + +def getPartitionUUID(partition): + return callString(["blkid","-o","value","-s","UUID",partition]) + +def setKbLayout(kb): + call(["loadkeys",kb]) + +def resetKbLayout(): + call(["service","console-setup.sh","restart"]) + call(["udevadm","trigger","--subsystem-match=input","--action=change"]) + call(["service","keyboard-setup.sh","restart"]) + +def ipth(path = ""): + return "/media/install/" +path + +def mkdirp(path): + if not os.path.isdir(path): os.makedirs(path) + +def chroot(path,cmd,*args,**kwargs): + dirs = ["dev","dev/pts","sys","proc"] + try: + for dir in dirs: + call(["mount","-o","bind","/" +dir,path + "/" +dir]) + call(["chroot",path] + cmd,*args,**kwargs) + for dir in reversed(dirs): + call(["umount","-l",path + "/" +dir]) + except Exception as e: + for dir in reversed(dirs): + try: + call(["umount","-l",path + "/" +dir]) + except: + pass + raise e + +def randhex(length): + chars = "0123456789ABCDEF" + output = "" + cLength = 0 + while cLength < length: + output = output + chars[random.randrange(0,15)] + cLength += 1 + return output + +def main(): + while choiceYn("Partition disk?"): + try: + disk = choice("Disk",getDisks()) + call(["fdisk",disk]) + except KeyboardInterrupt: + pass + + installPartition = choice("OS Partition",getPartitions()) + formatPartition = choiceYn("Format partition?","y") + if formatPartition: + fileSystems = [] + for path in os.environ["PATH"].split(":"): + if not os.path.isdir(path): continue + for root,dirs,files in os.walk(path): + for file in files: + ffile = os.path.join(root,file) + lfile = ffile.replace(path + os.path.sep,"",1) + if lfile.startswith("mkfs."): fileSystems.append(lfile.replace("mkfs.","",1)) + + fileSystems.sort() + defaultChoice = None + if "ext4" in fileSystems: defaultChoice = "ext4" + formatPartition = choice("File system",fileSystems,defaultChoice) + else: + formatPartition = None + + if formatPartition != None: + encrypt = choiceYn("Encrypt data?") + if encrypt: + encryptionPasswords = [] + setKbLayout("us") + try: + encryptionPasswords.append(choicePass("Encryption password")) + except KeyboardInterrupt: + encrypt = False + resetKbLayout() + + if encrypt: + while choiceYn("Add another password?"): + setKbLayout("us") + try: + encryptionPasswords.append(choicePass("Encryption password")) + except KeyboardInterrupt: + resetKbLayout() + break + resetKbLayout() + + installGRUB = choiceYn("Install GRUB?","y") + if installGRUB: + try: + grubDisk = choice("GRUB disk",getDisks()) + except KeyboardInterrupt: + installGRUB = False + + print("") + print("The rest of this setup will continue without your input ...") + time.sleep(5) + print("") + + print("> Wiping partition signature ...") + call(["wipefs","-a",installPartition]) + + if encrypt: + print("> Encrypting partition ...") + call(["apt","-y","install","cryptsetup"],stdout=subprocess.DEVNULL) + cryptPartition = installPartition + + mainPass = encryptionPasswords.pop(0) + proc = subprocess.Popen(["cryptsetup","luksFormat","--type","luks1",cryptPartition],stdin=subprocess.PIPE) + proc.stdin.write((mainPass + "\n").encode("utf-8")) + proc.stdin.flush() + checkProc(proc) + + for passw in encryptionPasswords: + print("Adding another password ...") + proc = subprocess.Popen(["cryptsetup","luksAddKey",cryptPartition],stdin=subprocess.PIPE) + proc.stdin.write((mainPass + "\n" + passw + "\n").encode("utf-8")) + proc.stdin.flush() + checkProc(proc) + + print("Creating block device ...") + proc = subprocess.Popen(["cryptsetup","luksOpen",cryptPartition,"system"],stdin=subprocess.PIPE) + proc.stdin.write((mainPass + "\n").encode("utf-8")) + proc.stdin.flush() + checkProc(proc) + installPartition = "/dev/mapper/system" + + if formatPartition != None: + print("> Formatting partition ...") + call(["mkfs." +formatPartition,installPartition]) + + print("> Grabbing partition UUIDs ...") + installPartitionUUID = getPartitionUUID(installPartition) + if encrypt: cryptPartitionUUID = getPartitionUUID(cryptPartition) + + print("> Mounting main partition ...") + mkdirp(ipth()) + call(["mount",installPartition,ipth()]) + + print("> Creating swap ...") + call(["dd","if=/dev/zero","of=" +ipth("swap"),"bs=1M","count=512","status=progress"]) + call(["chmod","600",ipth("swap")]) + call(["mkswap",ipth("swap")]) + call(["swapon",ipth("swap")]) + + print("> Adding files ...") + call(["unsquashfs","-f","-d",ipth(),"/lib/live/mount/medium/live/filesystem.squashfs"]) + + print("Setting hostname ...") + hostname = randhex(8) + fh = open(ipth("etc/hostname"),"w") + fh.write(hostname + "\n") + fh.close() + + if encrypt: + print("Writing crypto grub config ...") + fh = open(ipth("etc/default/grub.d/cryptodisk.cfg"),"w") + fh.write("GRUB_ENABLE_CRYPTODISK=y\n") + fh.write('GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX cryptdevice=UUID=' +cryptPartitionUUID+ ' root=UUID=' +installPartitionUUID+ '"\n') + fh.close() + + print("Writing crypttab ...") + fh = open(ipth("etc/crypttab"),"w") + fh.write('system UUID=' +cryptPartitionUUID+ ' none luks\n') + fh.close() + + print("Writing fstab ...") + fh = open(ipth("etc/fstab"),"w") + fh.write('UUID=' +installPartitionUUID+ ' / ' +getPartitionType(installPartition)+ ' defaults 0 1\n') + fh.write('/swap none swap sw 0 0\n') + fh.close() + + print("Copying keyboard settings ...") + shutil.copyfile("/etc/default/keyboard",ipth("etc/default/keyboard")) + + print("> Removing live-specific packages ...") + chroot(ipth(),["apt","-y","remove","live-boot","live-boot-initramfs-tools"]) + chroot(ipth(),["apt","-y","autoremove"]) + os.remove(ipth("bin/login")) + os.rename(ipth("bin/login.oobe"),ipth("bin/login")) + + if encrypt: + print("> Installing encryption-specific packages ...") + chroot(ipth(),["apt","-y","install","cryptsetup-initramfs"]) + else: + print("> Updating initramfs ...") + chroot(ipth(),["update-initramfs","-u"]) + + if installGRUB: + print("> Installing GRUB") + mbrInstall = True + diskType = getDiskType(grubDisk) + if diskType == "gpt": + print("Scanning GPT disk ...") + partitions = callList(["lsblk",grubDisk,"-no","PATH"]) + + del partitions[0] + try: + del partitions[partitions.index(installPartition)] + except Exception: + pass + + if crypto: + try: + del partitions[partitions.index(cryptoPartition)] + except Exception: + pass + + if len(partitions) > 0: + partType = getPartitionType(partitions[0]) + if partType == "fat" or partType == "vfat": + print("Mounting ESP ...") + mkdirp(ipth("boot/efi")) + call(["mount",partitions[0],ipth("boot/efi")]) + print("Installing GRUB ...") + mbrInstall = False + chroot(ipth(),["grub-install","--target=i386-efi","--uefi-secure-boot","--efi-directory=/boot/efi","--boot-directory=/boot",grubDisk]) + chroot(ipth(),["grub-install","--target=x86_64-efi","--uefi-secure-boot","--efi-directory=/boot/efi","--boot-directory=/boot",grubDisk]) + chroot(ipth(),["grub-install","--target=i386-pc","--boot-directory=/boot",grubDisk]) + chroot(ipth(),["update-grub"]) + print("Unmounting ESP ...") + call(["umount","-l",ipth("boot/efi")]) + os.rmdir(ipth("boot/efi")) + + if mbrInstall: + if diskType == "gpt": + print("WARNING: GPT disk unsuitable for EFI, installing BIOS payload only.") + print("Installing GRUB ...") + chroot(ipth(),["grub-install","--target=i386-pc","--boot-directory=/boot",grubDisk]) + chroot(ipth(),["update-grub"]) + + print("> Unmounting ...") + call(["swapoff",ipth("swap")]) + call(["umount",ipth()]) + os.rmdir(ipth()) + if encrypt: call(["cryptsetup","luksClose","system"]) + + print("Success. Press ENTER to quit setup.") + input() + +main() \ No newline at end of file diff --git a/mods/live-installer/modscript b/mods/live-installer/modscript index 609e325..b495431 100644 --- a/mods/live-installer/modscript +++ b/mods/live-installer/modscript @@ -1,4 +1,4 @@ #!/bin/bash -export WDVN_PACKAGES="$WDVN_PACKAGES gdisk dosfstools squashfs-tools console-data" -export WDVN_REMOVE="$WDVN_REMOVE dosfstools squashfs-tools" +export WDVN_PACKAGES="$WDVN_PACKAGES btrfs-progs squashfs-tools console-data python3" +export WDVN_REMOVE="$WDVN_REMOVE squashfs-tools" cp "$1/bin/login" "$1/bin/login.oobe" \ No newline at end of file