Skip to content

Instantly share code, notes, and snippets.

@nahidtislam
Forked from ReturnRei/Arch on Mac M1.txt
Last active November 29, 2022 19:29
Show Gist options
  • Save nahidtislam/2a059c0ea1e2fa2577fdbefb51d79d5b to your computer and use it in GitHub Desktop.
Save nahidtislam/2a059c0ea1e2fa2577fdbefb51d79d5b to your computer and use it in GitHub Desktop.
install Arch Linux ARM on Parallels (Apple Silicon)
### ReturnRei's youtube video provides a very helpful tutorial
### https://www.youtube.com/watch?v=dKvetujHjYQ&t=737s
#### PLEASE NOTE::
#### I created the Arch (target) VM (from the get go) and booted that with an Ubuntu CD
#### I think it's easier to do it that rather than to mess around with an existing vm
## his useful links
# https://wiki.archlinux.org/title/Install_Arch_Linux_from_existing_Linux#Using_a_chroot_environment
# https://archlinuxarm.org/platforms/armv8/generic
# https://www.reddit.com/r/archlinux/comments/6kwt61/systemd_doesnt_create_machineid_during/
# https://arm.endeavouros.com/endeavouros-arm-install/
#
## I don't make/use arch install scripts
## however ReturnRei's way is the only way I can get
## Arch working on my M1 Pro MacBook lol
#
# note I changed some words/commands to suit my locale (someone from the UK)
## download the the thing
cd ~/Downloads
wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
sudo add-apt-repository universe
sudo add-apt-repository multiverse
sudo apt update
sudo apt install libarchive-tools
sudo bash
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
TGTDEV="/dev/sda"
# partitions the drive
## do not run if you already done this manually
prep-disk() {
sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' <<E_FDISK | fdisk ${TGTDEV}
g # clear and and make the GPT table
n # new partition for EFI
1 # partition number 1
# (default) - start at beginning of disk
+1000M # 1GB (1000MB) boot parttion
t # set partition '1' type
1 # to "EFI System"
n # new partition
2 # partition number 2
# (default) - start immediately after preceding partition
# (default) - extend partition to end of disk
w # write the partition table to disc
q # and we're done
E_FDISK
mkfs.ext4 ${TGTDEV}2 -L "arch"
mkfs.vfat ${TGTDEV}1 -n "efi arm"
mkdir /target
mount ${TGTDEV}2 /target
mkdir /target/boot
mount ${TGTDEV}1 /target/boot
}
prep-disk ## RUNNING THIS WILL ERASE THE DATA IF YOUR USING AN EXISTING VM
## DO NOT RUN IF YOU ALREADY PARTITIONED YOUR DRIVE
bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C /target
echo "$TGTDEV" > /target/.initial_dev.text
## Get into chroot
mount --bind /target /target &&
cd /target &&
rm /target/etc/resolv.conf &&
cp /etc/resolv.conf etc &&
mount -t proc /proc proc &&
mount --make-rslave --rbind /sys sys &&
mount --make-rslave --rbind /dev dev &&
mount --make-rslave --rbind /run run
chroot /target /bin/bash #<<"E_CHROOT_ENV"
PS1='\[\033[01;31m\](chroot)\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]\$ '
chmod 755 /
TGTDEV="$(cat /.initial_dev.text)" # remember the TGTDEV before chrooting
mount ${TGTDEV}1 /boot
## prepare the pacman keys
pacman-key --init
pacman-key --populate archlinuxarm
## config the install
pacman -Syy --noconfirm vim zsh dash
# you can run this if you want pacman to look cool and fast
sed -i '/^#\(Color\|VerbosePkgLists\|ParallelDownloads\)/s/^#//' /etc/pacman.conf
# sets the simultaneous downloads to 6
sed -i 's/^ParallelDownloads = .*/ParallelDownloads = 6/' /etc/pacman.conf
# cool 8-bit pacman effect!
sed -i '/^#\?ParallelDownloads = /a ILoveCandy' /etc/pacman.conf
vim /etc/pacman.conf # do your own pacman config
EDITOR="vim"
## commands for install
pacman -Su --needed --noconfirm base linux linux-firmware arch-install-scripts \
efibootmgr networkmanager network-manager-applet \
dialog os-prober mtools dosfstools base-devel \
linux-headers git go
## internal arch system config
dbus-uuidgen > /etc/machine-id ## fix for missing machine-id
genfstab -U / | grep -e "UUID\|${TGTDEV}" >> /etc/fstab
ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime ## this is for if your located in Europe with London's timezone
hwclock --systohc
# edit /etc/locale.gen to select your locales
sed -i '/^#en_\(US\|GB\)[.]UTF-8/s/^#//' /etc/locale.gen
locale-gen
echo "LANG=en_GB.UTF-8" >> /etc/locale.conf ## assuming you want this locale
echo "parallels-arch-vm" >> /etc/hostname
groupadd sudo
useradd -m -G sudo -s /bin/zsh someuser
visudo # give yourself sudo access before rebooting
sed -i '/^#\s\+%sudo/s/^#\s\+//' /etc/sudoers ## scripty version
ln -sfT dash /usr/bin/sh # optional: makes your system bit more effcient
cat <<E_HOSTS > /etc/hosts
127.0.0.1 localhost
::1 localhost
E_HOSTS
systemctl enable NetworkManager
### setting up systemd-boot
bootctl --path=/boot install
cat <<E_BLOADER > /boot/loader/loader.conf
timeout 3
#console-mode keep
default arch*
E_BLOADER
cat <<E_BENTRY > /boot/loader/entries/arch.conf
title arch linux
linux /Image
initrd /initramfs-linux.img
options root=UUID=$(findmnt / -no UUID) rw quiet loglevel=3
E_BENTRY
# installing yay
su someuser
cd /tmp
git clone https://aur.archlinux.org/yay.git
cd yay && makepkg -si
####################################################################
####################################################################
######### THIS IS THE UNINTENDED SCRIPT TO ########################
########## PERFORM THE THE INSTALLATION OF #########################
############## THE VIRTUAL MACHINE #############################
####################################################################
####################################################################
### ReturnRei's youtube video provides a very helpful tutorial
### https://www.youtube.com/watch?v=dKvetujHjYQ&t=737s
#### PLEASE NOTE::
#### I created the Arch (target) VM (from the get go) and booted that with an Ubuntu CD
#### I think it's easier to do it that rather than to mess around with an existing vm
#
## I don't make/use arch install scripts
## however ReturnRei's way is the only way I can get
## Arch working on my M1 Pro MacBook lol
#
# note I changed some words/commands to suit my locale (someone from the UK)
while getopts a:d:p:u: option
do
case "${option}"
in
a) ADDITIONAL_PKGS="${OPTARG//,/ }";;
u) FIRST_USER="$OPTARG";;
p) FIRST_PASSWORD="$OPTARG";;
d)
if [[ "$OPTARG" =~ ^(gnome|kde|plasma|xfce4?)$ ]]; then
PREFERED_DESKTOP="$OPTARG"
else
printf "%s\n" "warning: unsupported desktop env"; exit 1
fi
;;
*) printf "%s\n" "warning: invalid argument(s)"; exit 1;;
esac
done
if [ "$FIRST_USER" ] && ! [ "$FIRST_PASSWORD" ]; then
printf "%s\n" "error: password is required if username is given"
exit 2
fi
[ "$FIRST_USER" ] || FIRST_USER='someuser'
ARCH_TAR="ArchLinuxARM-aarch64-latest.tar.gz"
if ! [ -f "$ARCH_TAR" ]; then
# maybe we are not in the same pwd as the script location
cd "$(dirname "$0")"
# check again
if ! [ -f "$ARCH_TAR" ]; then
## download the the thing
[ -w "$PWD" ] || cd ~/Downloads
until wget -c http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz; do
printf "\n%s" "retrying download..."
sleep 4
printf "\n\n"
done
fi
fi
unset ARCH_TAR
if ! which bsdtar &> /dev/null; then
printf "%s\n" "configuring apt repositories"
sudo add-apt-repository -y universe multiverse &> /dev/null
DEPENDANCY_INSTALL_ATTEMPT="1"
MAX_DEPENDANCY_ATTEMPT="5"
printf "%s\n" "installing libarchive-tools to use bsdtar"
until sudo apt install -y libarchive-tools || [ "$DEPENDANCY_INSTALL_ATTEMPT" == "$MAX_DEPENDANCY_ATTEMPT" ] &> /dev/null; do
printf "%s\r" "attempt $DEPENDANCY_INSTALL_ATTEMPT of $MAX_DEPENDANCY_ATTEMPT failed; retrying..."
done
if [ "$DEPENDANCY_INSTALL_ATTEMPT" -gt "$MAX_DEPENDANCY_ATTEMPT" ]; then
printf "%s\n" "sorry: installing libarchive-tools failed. We can't continue"
exit 4
fi
fi
echo "$ADDITIONAL_PKGS" > /tmp/additional_packages.text
echo "$FIRST_USER" > /tmp/first_user.text
echo "$FIRST_PASSWORD" | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'arch-Installer[ARM64]{forPARALLELS}06' > /tmp/first_password.aes
[ "$PREFERED_DESKTOP" ] && echo "$PREFERED_DESKTOP" > /tmp/prefered_desktop.text
sudo bash << 'E_ROOTSHELL'
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
FIRST_USER="$(cat /tmp/first_user.text)"
TGTDEV=""
select-disk() {
declare -a DISKS
SELECTED_DISK=""
for disk in /dev/sd*[a-z]; do
# printf "%s\n" "$disk"
DISKS+=("$disk")
done
if [ "${#DISKS[@]}" -eq 0 ]; then
printf "%s\n" "error: No disks found" 1>&2
exit 1
elif [ "${#DISKS[@]}" -eq 1 ]; then
SELECTED_DISK=${DISKS[0]}
else
printf "%s\n%s\n" \
"there are more than one disk to select" \
"select the disk." 1>&2
i=0
for driveMount in "${DISKS[@]}"; do
i=$(( i+1 ))
printf "%s\n" "${i}. '${driveMount}'" 1>&2
done
unset i
if [ "${#DISKS[@]}" -gt 9 ]; then
digits=2
else
digits=1
fi
read -n ${digits} DRIVE_USER_SELECTION
printf "\n" 1>&2
if ! [ "${DRIVE_USER_SELECTION}" ] || [ "${DRIVE_USER_SELECTION}" -gt ${#DISKS[@]} ]; then
printf "%s\n" "error: bad selection" 1>&2
exit 3
fi
SELECTED_DISK=${DISKS[$(( DRIVE_USER_SELECTION-1 ))]}
unset DRIVE_USER_SELECTION
fi
if ! [ "${SELECTED_DISK}" ]; then
printf "%s\n" "error: Unable to determine disk" 1>&2
exit 4
fi
echo "$SELECTED_DISK"
}
TGTDEV="$(select-disk)"
if ! [ "$TGTDEV" ]; then
printf "%s\n" "error: disk selection failed"
exit 1
fi
# partitions the drive
## do not run if you already done this manually
prep-disk() {
sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' <<E_FDISK | fdisk ${TGTDEV} > /dev/null
g # clear and and make the GPT table
n # new partition for EFI
1 # partition number 1
# (default) - start at beginning of disk
+1000M # 1GB (1000MB) boot parttion
t # set partition '1' type
1 # to "EFI System"
n # new partition
2 # partition number 2
# (default) - start immediately after preceding partition
# (default) - extend partition to end of disk
w # write the partition table to disc
q # and we're done
E_FDISK
mkfs.ext4 ${TGTDEV}2 -L "arch" &> /dev/null
mkfs.vfat ${TGTDEV}1 -n "efi arm" &> /dev/null
mkdir /target
mount ${TGTDEV}2 /target
mkdir /target/boot
mount ${TGTDEV}1 /target/boot
}
if [ "$(ls "${TGTDEV}"*[0-9] 2> /dev/null)" ]; then
printf "%s\n" "WARNING: THIS DISK CONTAINS PARTITIONS"
printf "%s\n" " PONTENTIAL DATA LOSS COULD HAPPEN"
printf "\n"
read -e -p "continue? " RISK_DATA
[[ "$RISK_DATA" == [Yy]* ]] || exit 1
fi
prep-disk ## RUNNING THIS WILL ERASE THE DATA IF YOUR USING AN EXISTING VM
## DO NOT RUN IF YOU ALREADY PARTITIONED YOUR DRIVE
printf "%s\n" "success: formating $TGTDEV for install"
bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C /target
echo "$TGTDEV" > /target/.initial_dev.text
echo "$FIRST_USER" > /target/.initial_user.text
cp /tmp/additional_packages.text /target/.additional_packages.text
cp /tmp/first_password.aes /target/.initial_password.aes
cp /tmp/prefered_desktop.text /target/.prefered_desktop.text
## Get into chroot
mount --bind /target /target &&
cd /target &&
rm /target/etc/resolv.conf &&
cp /etc/resolv.conf etc &&
mount -t proc /proc proc &&
mount --make-rslave --rbind /sys sys &&
mount --make-rslave --rbind /dev dev &&
mount --make-rslave --rbind /run run
chroot /target /bin/bash << 'E_CHROOT_ENV'
PS1='\[\033[01;31m\](chroot)\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]\$ '
pac() {
until pacman -S --needed --noconfirm $@; do
printf "\n\n%s" "install of $1 failed; retrying..."
sleep 4
printf "\n\n\n"
done
}
chmod 755 /
ADDITIONAL_PKGS="$(cat /.additional_packages.text)"
TGTDEV="$(cat /.initial_dev.text)" # remember the TGTDEV before chrooting
FIRST_USER="$(cat /.initial_user.text)" # remember the option USER before chrooting
[ -f "/.prefered_desktop.text" ] && PREFERED_DESKTOP="$(cat /.prefered_desktop.text)"
mount ${TGTDEV}1 /boot
## prepare the pacman keys
pacman-key --init
pacman-key --populate archlinuxarm
## config the install
# you can run this if you want pacman to look cool and fast
sed -i '/^#\(Color\|VerbosePkgLists\|ParallelDownloads\)/s/^#//' /etc/pacman.conf
# sets the simultaneous downloads to 6
sed -i 's/^ParallelDownloads = .*/ParallelDownloads = 6/' /etc/pacman.conf
# cool 8-bit pacman effect!
sed -i '/^#\?ParallelDownloads = /a ILoveCandy' /etc/pacman.conf
## commands for install
until pacman -Syyu --needed --noconfirm base linux linux-firmware arch-install-scripts \
efibootmgr networkmanager network-manager-applet \
dialog os-prober mtools dosfstools base-devel \
linux-headers git go vim zsh dash
do
sleep 3.5
done
pacman -D --asdeps base linux-firmware arch-install-scripts \
efibootmgr networkmanager network-manager-applet \
dialog os-prober mtools dosfstools go zsh dash > /dev/null
EDITOR="vim"
## internal arch system config
dbus-uuidgen > /etc/machine-id ## fix for missing machine-id
genfstab -U / | grep -e "UUID\|${TGTDEV}" >> /etc/fstab
ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime ## this is for if your located in Europe with London's timezone
hwclock --systohc
# edit /etc/locale.gen to select your locales
sed -i '/^#en_\(US\|GB\)[.]UTF-8/s/^#//' /etc/locale.gen
locale-gen
echo "LANG=en_GB.UTF-8" >> /etc/locale.conf ## assuming you want this locale
echo "parallels-arch-vm" > /etc/hostname
# setting up user
groupadd sudo
useradd -m -G sudo -s /bin/zsh "$FIRST_USER"
if [ "$FIRST_USER" != "someuser" ]; then
FIRST_PASSWORD="$(cat /.initial_password.aes | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'arch-Installer[ARM64]{forPARALLELS}06')"
echo -e "${FIRST_PASSWORD}\n${FIRST_PASSWORD}" | passwd $FIRST_USER &> /dev/null
else
echo -e "someuser\nsomeuser" | passwd someuser &> /dev/null
FIRST_PASSWORD="someuser"
fi
usermod -a -G wheel $FIRST_USER
# give yourself sudo access before rebooting
sed -i '/^#\s\+%sudo/s/^#\s\+//' /etc/sudoers ## scripty version
# to smooth out the yay package installations
# as running yay as root isn't available
echo "$FIRST_USER ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/yay-smoother
# this is to let pamac open to users in the 'sudo' group
cat <<E_PADMIN > /etc/polkit-1/rules.d/51-allow-sudo-group.rules
//
// this is to allow users in the sudo group to access privileged GUI apps
// like they do with wheel
//
// useful for apps like pamac
polkit.addAdminRule(function(action, subject) {
return ["unix-group:sudo"];
});
E_PADMIN
ln -sfT dash /usr/bin/sh # optional: makes your system bit more effcient
cat <<E_HOSTS > /etc/hosts
127.0.0.1 localhost
::1 localhost
E_HOSTS
echo -e "toor\ntoor" | passwd &> /dev/null
systemctl enable NetworkManager
### setting up systemd-boot
bootctl --path=/boot install
cat <<E_BLOADER > /boot/loader/loader.conf
timeout 1
#console-mode keep
default arch*
E_BLOADER
cat <<E_BENTRY > /boot/loader/entries/arch.conf
title arch linux
linux /Image
initrd /initramfs-linux.img
options root=UUID=$(findmnt / -no UUID) rw quiet loglevel=3
E_BENTRY
rm /.initial_dev.text
rm /.initial_user.text
rm /.initial_password.aes
# installing yay
su - "$FIRST_USER" <<E_YAY
cd /tmp
git clone https://aur.archlinux.org/yay.git
cd yay && makepkg -s
sudo pacman -U --noconfirm yay-*.pkg.tar.xz
E_YAY
[ "$PREFERED_DESKTOP" ] && case "$PREFERED_DESKTOP"
in
gnome)
#### WE NEED TO EXCLUDE SOME PACKAGES THAT MIGHT NOT WORK ON ARM64 ###
SKIP_GPKG=("gnome" "gnome-books" "gnome-boxes" "gnome-contacts" "gnome-music" "gnome-photos" "gnome-weather" "gnome-maps" "gnome-remote-desktop" "gnome-software" "gnome-user-docs" "cheese" "simple-scan" "qemu")
GNOME_PKGS=""
for pkg in $(pacman -Sqg gnome); do
[[ " ${SKIP_GPKG[*]} " =~ " $pkg " ]] || GNOME_PKGS+=" $pkg"
done
GNOME_PKGS="${GNOME_PKGS:1}"
printf "\n\n%s\n" "insatlling gnome ---"
printf " %s\n" "> pacman > $GNOME_PKGS"
pac $GNOME_PKGS gdm
pacman -D --asdeps $GNOME_PKGS > /dev/null
pacman -D --asexplicit gnome > /dev/null
systemctl enable gdm
unset SKIP_GPKG
unset GNOME_PKGS
;;
kde|plasma)
"\n\n%s\n" "insatlling kde ---"
pac plasma plasma-wayland-session xorg xorg-server sddm
systemctl enable sddm
;;
xfce|xfce4)
"\n\n%s\n" "insatlling kde ---"
pac xfce4-sessionxorg xorg-server lightdm lightdm-slick-greeter
systemctl enable lightdm
;;
*)
printf "%s\n" "warning: invalid desktop option - skipping";;
esac
[ "$PREFERED_DESKTOP" ] && su - "$FIRST_USER" <<E_PAMAC
cd /tmp
yay -Sy --noconfirm pamac-aur
E_PAMAC
[ "$ADDITIONAL_PKGS" ] && pac $ADDITIONAL_PKGS
rm "/.prefered_desktop.text"
rm "/.additional_packages.text"
rm "/etc/sudoers.d/yay-smoother"
OLD_alarm_USERID="$(cat /etc/passwd | grep "alarm" | cut -f3 -d':')"
usermod -u 818 alarm
find / -uid "$OLD_alarm_USERID" -exec chown alarm {} \; &> /dev/null
[ "$FIRST_USER" == "someuser" ] && passwd --expire someuser
E_CHROOT_ENV
E_ROOTSHELL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment