New install.sh
This commit is contained in:
parent
bffea892e6
commit
6dd20fb291
1 changed files with 115 additions and 219 deletions
334
install.sh
334
install.sh
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# Arch Linux installation
|
# Bootstrap a new Arch system from an installation ISO.
|
||||||
#
|
#
|
||||||
# Bootable USB:
|
# Bootable USB:
|
||||||
# - [Download](https://archlinux.org/download/) ISO and GPG files
|
# - [Download](https://archlinux.org/download/) ISO and GPG files
|
||||||
|
@ -13,284 +13,180 @@
|
||||||
# - Temporarily disable Secure Boot.
|
# - Temporarily disable Secure Boot.
|
||||||
# - Make sure a strong UEFI administrator password is set.
|
# - Make sure a strong UEFI administrator password is set.
|
||||||
# - Delete preloaded OEM keys for Secure Boot, allow custom ones.
|
# - Delete preloaded OEM keys for Secure Boot, allow custom ones.
|
||||||
# - Set SATA operation to AHCI mode.
|
|
||||||
#
|
#
|
||||||
# Run installation:
|
# Run installation:
|
||||||
#
|
#
|
||||||
# - Connect to wifi via: `# iwctl station wlan0 connect WIFI-NETWORK`
|
# - Connect to wifi via: `# iwctl station wlan0 connect $SSID`
|
||||||
# - Run: `# bash <(curl -sL https://link.rafe.li/dot)`
|
# - Run: `# bash <(curl -sL https://link.rafe.li/dot)`
|
||||||
#
|
#
|
||||||
# WARNING: this script will destroy data on the selected disk.
|
|
||||||
#
|
|
||||||
|
|
||||||
set -uo pipefail
|
set -xeuo pipefail
|
||||||
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
|
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
|
||||||
|
|
||||||
exec 1> >(tee "stdout.log")
|
exec 1> >(tee "/root/stdout.log")
|
||||||
exec 2> >(tee "stderr.log" >&2)
|
exec 2> >(tee "/root/stderr.log" >&2)
|
||||||
|
|
||||||
export SNAP_PAC_SKIP=y
|
args=()
|
||||||
|
target_device=""
|
||||||
|
new_hostname=""
|
||||||
|
|
||||||
umount -R /mnt 2> /dev/null || true
|
while [[ $# -gt 0 ]]
|
||||||
swapoff --all
|
do
|
||||||
cryptsetup close swap 2> /dev/null || true
|
arg="$1"
|
||||||
cryptsetup luksClose system 2> /dev/null || true
|
|
||||||
|
|
||||||
# Dialog
|
case "$arg" in
|
||||||
BACKTITLE="Arch Linux installation"
|
"--device")
|
||||||
|
target_device="$2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"--hostname")
|
||||||
|
new_hostname="$2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
args+=("$arg")
|
||||||
|
shift;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
get_input() {
|
if [[ -z "$target_device" ]]; then
|
||||||
title="$1"
|
echo "Missing --device <device> argument" >&2
|
||||||
description="$2"
|
exit 2;
|
||||||
|
fi
|
||||||
|
|
||||||
input=$(dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --inputbox "$description" 0 0)
|
if [[ -z "$new_hostname" ]]; then
|
||||||
echo "$input"
|
echo "Missing --hostname <hostname> argument" >&2
|
||||||
}
|
exit 2;
|
||||||
|
fi
|
||||||
|
|
||||||
get_password() {
|
if [[ "${#args[@]}" -ne 0 ]]; then
|
||||||
title="$1"
|
echo "Unexpected extra arguments: ${args[*]}" >&2
|
||||||
description="$2"
|
exit 2
|
||||||
while : ; do
|
fi
|
||||||
init_pass=$(dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --passwordbox "$description" 0 0)
|
|
||||||
: "${init_pass:?dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --msgbox "Password cannot be empty.\nTry again." 0 0}"
|
|
||||||
|
|
||||||
test_pass=$(dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --passwordbox "$description again" 0 0)
|
|
||||||
if [[ "$init_pass" != "$test_pass" ]]; then
|
|
||||||
dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --msgbox "Passwords did not match.\nTry again." 0 0
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "$init_pass"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_choice() {
|
|
||||||
title="$1"
|
|
||||||
description="$2"
|
|
||||||
shift 2
|
|
||||||
options=("$@")
|
|
||||||
dialog --clear --stdout --backtitle "$BACKTITLE" --title "$title" --menu "$description" 0 0 0 "${options[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
echo -e "\n### Checking UEFI boot mode"
|
|
||||||
if [ ! -f /sys/firmware/efi/fw_platform_size ]; then
|
if [ ! -f /sys/firmware/efi/fw_platform_size ]; then
|
||||||
echo >&2 "You must boot in UEFI mode to continue"
|
echo >&2 "You must boot in UEFI mode to continue"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\n### Ensure the system clock is accurate"
|
if [[ "$UID" -ne 0 ]]; then
|
||||||
|
echo "This script needs to be run as root!" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -rp "THIS SCRIPT WILL OVERWRITE ALL CONTENTS OF ${target_device}. Type uppercase yes to continue: " confirmed
|
||||||
|
|
||||||
|
if [[ "$confirmed" != "YES" ]]; then
|
||||||
|
echo "aborted" >&2
|
||||||
|
exit 128
|
||||||
|
fi
|
||||||
|
|
||||||
timedatectl set-ntp true
|
timedatectl set-ntp true
|
||||||
hwclock --systohc --utc
|
hwclock --systohc --utc
|
||||||
|
|
||||||
echo -e "\n### Setting keyboard layout to de-latin1"
|
|
||||||
loadkeys de-latin1
|
loadkeys de-latin1
|
||||||
|
|
||||||
echo -e "\n### Installing additional tools"
|
# Partition
|
||||||
pacman -Sy --noconfirm --needed git reflector terminus-font dialog wget
|
sgdisk --zap-all "${target_device}"
|
||||||
|
|
||||||
echo -e "\n### HiDPI screens"
|
|
||||||
noyes=("Yes" "The font is too small" "No" "The font size is just fine")
|
|
||||||
hidpi=$(get_choice "Font size" "Is your screen HiDPI?" "${noyes[@]}") || exit 1
|
|
||||||
clear
|
|
||||||
[[ "$hidpi" == "Yes" ]] && font="ter-132n" || font="ter-716n"
|
|
||||||
setfont "$font"
|
|
||||||
|
|
||||||
hostname=$(get_input "Hostname" "Enter hostname") || exit 1
|
|
||||||
clear
|
|
||||||
: "${hostname:?"hostname cannot be empty"}"
|
|
||||||
|
|
||||||
user=$(get_input "User" "Enter username") || exit 1
|
|
||||||
clear
|
|
||||||
: "${user:?"user cannot be empty"}"
|
|
||||||
|
|
||||||
password=$(get_password "User" "Enter password") || exit 1
|
|
||||||
clear
|
|
||||||
: "${password:?"password cannot be empty"}"
|
|
||||||
|
|
||||||
devicelist=$(lsblk -dplnx size -o name,size | grep -Ev "boot|rpmb|loop" | tac | tr '\n' ' ')
|
|
||||||
read -r -a devicelist <<< "$devicelist"
|
|
||||||
|
|
||||||
device=$(get_choice "Installation" "Select installation disk" "${devicelist[@]}") || exit 1
|
|
||||||
|
|
||||||
clear
|
|
||||||
|
|
||||||
echo -e "\n### Setting up fastest mirrors"
|
|
||||||
reflector --country 'Germany,France' --protocol https --sort rate --latest 5 --save /etc/pacman.d/mirrorlist
|
|
||||||
|
|
||||||
echo -e "\n### Setting up partitions"
|
|
||||||
sgdisk --zap-all "${device}"
|
|
||||||
sgdisk --clear \
|
sgdisk --clear \
|
||||||
--new=1:0:+550MiB --typecode=1:ef00 --change-name=1:EFI \
|
--new 1:0:+550MiB --typecode 1:ef00 --change-name 1:EFI \
|
||||||
--new=2:0:+8GiB --typecode=2:8200 --change-name=2:cryptswap \
|
--new 2:0:+8GiB --typecode 2:8200 --change-name 2:swap \
|
||||||
--new=3:0:0 --typecode=3:8300 --change-name=3:cryptsystem \
|
--new 3 --typecode 3:8304 --change-name 3:system \
|
||||||
"${device}"
|
"${target_device}"
|
||||||
|
|
||||||
|
# Reload partition table
|
||||||
sleep 5
|
sleep 5
|
||||||
|
partprobe -s "${target_device}"
|
||||||
|
sleep 3
|
||||||
|
|
||||||
echo -e "\n### Formatting partitions"
|
# Encrypt root
|
||||||
# Boot partition
|
echo -n "password" | cryptsetup luksFormat --type luks2 --pbkdf argon2id "/dev/disk/by-partlabel/system"
|
||||||
|
echo -n "password" | cryptsetup luksOpen --allow-discards --persistent "/dev/disk/by-partlabel/system" system
|
||||||
|
|
||||||
|
# Create file systems
|
||||||
mkfs.fat -F 32 -n "EFI" /dev/disk/by-partlabel/EFI
|
mkfs.fat -F 32 -n "EFI" /dev/disk/by-partlabel/EFI
|
||||||
|
|
||||||
# Swap partition
|
|
||||||
cryptsetup open --type plain --key-file /dev/urandom /dev/disk/by-partlabel/cryptswap swap
|
|
||||||
mkswap -L swap /dev/mapper/swap
|
|
||||||
swapon -L swap
|
|
||||||
|
|
||||||
# System partition
|
|
||||||
echo -n "${password}" | cryptsetup luksFormat --type luks2 --pbkdf argon2id "/dev/disk/by-partlabel/cryptsystem"
|
|
||||||
echo -n "${password}" | cryptsetup luksOpen --allow-discards --persistent "/dev/disk/by-partlabel/cryptsystem" system
|
|
||||||
mkfs.btrfs --force --label system /dev/mapper/system
|
mkfs.btrfs --force --label system /dev/mapper/system
|
||||||
|
|
||||||
echo -e "\n### Setting up BTRFS subvolumes"
|
# Mount system subvolume and create additional subvolumes
|
||||||
o=defaults,x-mount.mkdir
|
o=defaults,x-mount.mkdir
|
||||||
o_btrfs=$o,compress=zstd,ssd,noatime
|
o_btrfs=$o,compress=zstd,ssd,noatime
|
||||||
|
|
||||||
mount -t btrfs LABEL=system /mnt
|
mount -t btrfs LABEL=system /mnt
|
||||||
btrfs subvolume create /mnt/root
|
btrfs subvolume create /mnt/@ # /
|
||||||
btrfs subvolume create /mnt/home
|
btrfs subvolume create /mnt/@home # /home
|
||||||
btrfs subvolume create /mnt/snapshots
|
btrfs subvolume create /mnt/@snapshots # /.snapshots
|
||||||
btrfs subvolume create /mnt/pkgs
|
btrfs subvolume create /mnt/@pkg # /var/cache/pacman/pkg
|
||||||
btrfs subvolume create /mnt/aurbuild
|
btrfs subvolume create /mnt/@aurbuild # /var/lib/aurbuild
|
||||||
btrfs subvolume create /mnt/archbuild
|
btrfs subvolume create /mnt/@archbuild # /var/lib/archbuild
|
||||||
btrfs subvolume create /mnt/docker
|
btrfs subvolume create /mnt/@log # /var/log
|
||||||
btrfs subvolume create /mnt/logs
|
btrfs subvolume create /mnt/@tmp # /var/tmp
|
||||||
btrfs subvolume create /mnt/tmp
|
|
||||||
umount -R /mnt
|
umount -R /mnt
|
||||||
|
mount -t btrfs -o subvol=@,$o_btrfs LABEL=system /mnt
|
||||||
|
mount -t btrfs -o subvol=@home,$o_btrfs,nodatacow LABEL=system /mnt/home
|
||||||
|
mount -t btrfs -o subvol=@snapshots,$o_btrfs LABEL=system /mnt/.snapshots
|
||||||
|
mount -t btrfs -o subvol=@pkg,$o_btrfs LABEL=system /mnt/var/cache/pacman/pkg
|
||||||
|
mount -t btrfs -o subvol=@aurbuild,$o_btrfs LABEL=system /mnt/var/lib/aurbuild
|
||||||
|
mount -t btrfs -o subvol=@archbuild,$o_btrfs LABEL=system /mnt/var/lib/archbuild
|
||||||
|
mount -t btrfs -o subvol=@log,$o_btrfs LABEL=system /mnt/var/log
|
||||||
|
mount -t btrfs -o subvol=@tmp,$o_btrfs LABEL=system /mnt/var/tmp
|
||||||
|
|
||||||
mount -t btrfs -o subvol=root,$o_btrfs LABEL=system /mnt
|
# Mount additional partitions
|
||||||
mount -t btrfs -o subvol=home,$o_btrfs LABEL=system /mnt/home
|
|
||||||
mount -t btrfs -o subvol=snapshots,$o_btrfs LABEL=system /mnt/.snapshots
|
|
||||||
mount -t btrfs -o subvol=pkgs,$o_btrfs LABEL=system /mnt/var/cache/pacman
|
|
||||||
mount -t btrfs -o subvol=aurbuild,$o_btrfs LABEL=system /mnt/var/lib/aurbuild
|
|
||||||
mount -t btrfs -o subvol=archbuild,$o_btrfs LABEL=system /mnt/var/lib/archbuild
|
|
||||||
mount -t btrfs -o subvol=docker,$o_btrfs LABEL=system /mnt/var/lib/docker
|
|
||||||
mount -t btrfs -o subvol=logs,$o_btrfs LABEL=system /mnt/var/log
|
|
||||||
mount -t btrfs -o subvol=tmp,$o_btrfs LABEL=system /mnt/var/tmp
|
|
||||||
|
|
||||||
mount -o $o LABEL=EFI /mnt/efi
|
mount -o $o LABEL=EFI /mnt/efi
|
||||||
|
|
||||||
echo -e "\n### Configuring custom repo"
|
# Disable CoW for /home due to large loopback files by systemd-homed
|
||||||
mkdir "/mnt/var/cache/pacman/${user}-local"
|
chattr +C /mnt/home
|
||||||
|
|
||||||
# if [[ "${user}" == "maximbaz" && "${hostname}" == "home-"* ]]; then
|
if ! grep "# Installer cache" /etc/pacman.conf > /dev/null; then
|
||||||
# wget -m -nH -np -q --show-progress --progress=bar:force --reject='index.html*' --cut-dirs=2 -P "/mnt/var/cache/pacman/${user}-local" 'https://pkgbuild.com/~maximbaz/repo/'
|
|
||||||
# rename -- 'maximbaz.' "${user}-local." "/mnt/var/cache/pacman/${user}-local"/*
|
|
||||||
# else
|
|
||||||
repo-add "/mnt/var/cache/pacman/${user}-local/${user}-local.db.tar"
|
|
||||||
# fi
|
|
||||||
|
|
||||||
if ! grep "${user}" /etc/pacman.conf > /dev/null; then
|
|
||||||
cat >> /etc/pacman.conf << EOF
|
cat >> /etc/pacman.conf << EOF
|
||||||
|
# Installer cache
|
||||||
[${user}-local]
|
|
||||||
Server = file:///mnt/var/cache/pacman/${user}-local
|
|
||||||
|
|
||||||
[maximbaz]
|
|
||||||
Server = https://pkgbuild.com/~maximbaz/repo/x86_64/
|
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
CacheDir = /mnt/var/cache/pacman/pkg
|
CacheDir = /mnt/var/cache/pacman/pkg
|
||||||
CacheDir = /mnt/var/cache/pacman/${user}-local
|
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\n### Installing packages"
|
# Bootstrap new chroot
|
||||||
kernel_packages=(
|
reflector --country 'Germany' --protocol https --sort age --latest 5 --save /etc/pacman.d/mirrorlist
|
||||||
"linux"
|
pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim iwd networkmanager
|
||||||
"linux-headers"
|
|
||||||
"linux-lts"
|
|
||||||
"linux-firmware"
|
|
||||||
"intel-ucode"
|
|
||||||
)
|
|
||||||
fs_packages=(
|
|
||||||
"btrfs-progs"
|
|
||||||
"dosfstools"
|
|
||||||
"e2fsprogs"
|
|
||||||
)
|
|
||||||
network_packages=(
|
|
||||||
"iwd"
|
|
||||||
"networkmanager"
|
|
||||||
)
|
|
||||||
basic_packages=(
|
|
||||||
"man-db"
|
|
||||||
"man-pages"
|
|
||||||
"pacman-contrib"
|
|
||||||
"neovim"
|
|
||||||
"bash-completion"
|
|
||||||
"git"
|
|
||||||
"rsync"
|
|
||||||
"openssh"
|
|
||||||
"htop"
|
|
||||||
"fzf"
|
|
||||||
"sudo"
|
|
||||||
)
|
|
||||||
#"pipewire"
|
|
||||||
#"pipewire-pulse"
|
|
||||||
#"pipewire-jack"
|
|
||||||
#"wireplumber"
|
|
||||||
#"firefox"
|
|
||||||
#"firefox-i18n-de"
|
|
||||||
#"firefox-ublock-origin"
|
|
||||||
#"firefox-dark-reader"
|
|
||||||
#"aurutils" # from maximbaz repo
|
|
||||||
#"devtools" # tools for aurutils
|
|
||||||
#"docbook-xls" # depenency of plymouth-git
|
|
||||||
#"efitools" # provides KeyTool
|
|
||||||
#"libfido2" # for systemd-cryptenroll
|
|
||||||
#"bluez"
|
|
||||||
#"bluez-utils"
|
|
||||||
#"usbutils" # for lsusb
|
|
||||||
#)
|
|
||||||
all_packages=(
|
|
||||||
${kernel_packages[@]}
|
|
||||||
${fs_packages[@]}
|
|
||||||
${network_packages[@]}
|
|
||||||
${basic_packages[@]}
|
|
||||||
)
|
|
||||||
|
|
||||||
pacstrap /mnt base base-devel arch-secure-boot chezmoi ${all_packages[@]}
|
|
||||||
|
|
||||||
echo -e "\n### Generating base config files"
|
|
||||||
genfstab -L -p /mnt >> /mnt/etc/fstab
|
genfstab -L -p /mnt >> /mnt/etc/fstab
|
||||||
sed -i "s+LABEL=swap+/dev/mapper/swap+" /mnt/etc/fstab
|
|
||||||
echo "cryptswap /dev/disk/by-partlabel/cryptswap /dev/urandom swap,cipher=aes-xts-plain64,size=256" >> /mnt/etc/crypttab
|
|
||||||
|
|
||||||
|
# Configure timezone, locale, keymap, network
|
||||||
sed -i 's/^#en_US\.UTF-8/en_US\.UTF-8/' /mnt/etc/locale.gen
|
sed -i 's/^#en_US\.UTF-8/en_US\.UTF-8/' /mnt/etc/locale.gen
|
||||||
sed -i 's/^#de_DE\.UTF-8/de_DE\.UTF-8/' /mnt/etc/locale.gen
|
sed -i 's/^#de_DE\.UTF-8/de_DE\.UTF-8/' /mnt/etc/locale.gen
|
||||||
arch-chroot /mnt locale-gen
|
arch-chroot /mnt locale-gen
|
||||||
|
|
||||||
arch-chroot /mnt systemd-firstboot \
|
arch-chroot /mnt systemd-firstboot \
|
||||||
--locale="en_US.UTF-8" \
|
--locale="en_US.UTF-8" \
|
||||||
--keymap="de-latin1" \
|
--keymap="de-latin1" \
|
||||||
--timezone="Europe/Berlin" \
|
--timezone="Europe/Berlin" \
|
||||||
--hostname="${hostname}" \
|
--hostname="${new_hostname}" \
|
||||||
--setup-machine-id
|
--setup-machine-id
|
||||||
echo "FONT=$font" > /mnt/etc/vconsole.conf
|
|
||||||
echo -e "127.0.0.1\tlocalhost" >> /mnt/etc/hosts
|
echo -e "127.0.0.1\tlocalhost" >> /mnt/etc/hosts
|
||||||
echo -e "127.0.1.1\t$hostname" >> /mnt/etc/hosts
|
echo -e "127.0.1.1\t$new_hostname" >> /mnt/etc/hosts
|
||||||
echo -e "\n::1\tlocalhost" >> /mnt/etc/hosts
|
echo -e "\n::1\tlocalhost" >> /mnt/etc/hosts
|
||||||
arch-chroot /mnt timedatectl set-ntp 1
|
|
||||||
|
|
||||||
echo -e "\n### Creating user"
|
# Use systemd-resolved as dns backend for NetworkManager (auto-detected)
|
||||||
arch-chroot /mnt useradd -m "$user"
|
ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
|
||||||
for group in wheel network video audio input storage power; do
|
|
||||||
arch-chroot /mnt groupadd -rf "$group"
|
|
||||||
arch-chroot /mnt gpasswd -a "$user" "$group"
|
|
||||||
done
|
|
||||||
echo "$user:$password" | arch-chroot /mnt chpasswd
|
|
||||||
|
|
||||||
echo -e "\n### Disabling root login"
|
# Enable iwd as wifi backend for NetworkManager
|
||||||
arch-chroot /mnt passwd -dl root
|
cat > /mnt/etc/NetworkManager/conf.d/wifi-backend.conf <<EOF
|
||||||
|
|
||||||
echo -e "\n### Setting permissions on the custom repo"
|
|
||||||
arch-chroot /mnt chown -R "$user:$user" "/var/cache/pacman/${user}-local/"
|
|
||||||
|
|
||||||
#echo -e "\n### Cloning dotfiles and running initial setup"
|
|
||||||
#arch-chroot /mnt sudo -u $user sh -c 'chezmoi init --apply https://code.strobeto.de/strobeltobias/dotfiles.git && chezmoi state delete-bucket --bucket=scriptState'
|
|
||||||
|
|
||||||
cat > /mnt/etc/NetworkManager/conf.d/wifi_backend.conf <<EOF
|
|
||||||
[device]
|
[device]
|
||||||
wifi.backend=iwd
|
wifi.backend=iwd
|
||||||
EOF
|
EOF
|
||||||
arch-chroot /mnt systemctl enable NetworkManager.service
|
|
||||||
echo -e "\n### DONE - reboot and re-run 'chezmoi apply' to complete system setup"
|
# Install dracut opt deps required to build unified kernel images
|
||||||
|
arch-chroot /mnt pacman -S --noconfirm --asdeps binutils elfutils
|
||||||
|
arch-chroot /mnt dracut -f --uefi --regenerate-all
|
||||||
|
# Install bootloader
|
||||||
|
arch-chroot /mnt bootctl install
|
||||||
|
|
||||||
|
# Enable resolved
|
||||||
|
systemctl --root /mnt enable systemd-resolved
|
||||||
|
# Enable homed
|
||||||
|
systemctl --root /mnt enable systemd-homed
|
||||||
|
|
||||||
|
# Set root password
|
||||||
|
echo -n "password" | passwd -R /mnt root
|
||||||
|
|
||||||
|
echo "BOOTSTRAPPING FINISHED"
|
||||||
|
|
Loading…
Reference in a new issue