Created
February 22, 2025 00:00
-
-
Save PhrozenByte/95933c32227c3b8e596c6e2267b60b2d to your computer and use it in GitHub Desktop.
Creates a live ISO of Arch Linux with GNOME.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# mkarchiso-gnome | |
# Creates a live ISO of Arch Linux with GNOME | |
# | |
# This script was created to ease creating live ISOs of Arch Linux with GNOME | |
# installed. It's highly customized to my personal preferences, thus it's | |
# likely not very useful as-is for most people, but it could be a good | |
# starting point for others to create their own custom live ISO. | |
# | |
# More about `mkarchiso`: https://wiki.archlinux.org/title/Archiso | |
# | |
# Copyright (C) 2025 Daniel Rudolf (<https://www.daniel-rudolf.de>) | |
# License: The MIT License <http://opensource.org/licenses/MIT> | |
# | |
# SPDX-License-Identifier: MIT | |
set -eu -o pipefail | |
export LC_ALL=C | |
APP_NAME="$(basename "${BASH_SOURCE[0]}")" | |
if [ -z "${1:-}" ]; then | |
echo "Usage" >&2 | |
echo " $APP_NAME OUTPUT_DIR" >&2 | |
exit 1 | |
fi | |
[ "$(id -u)" != 0 ] || { echo "You must not run \`$APP_NAME\` as root, but as \`sudo\`-able user" >&2; exit 1; } | |
[ -x "$(which git)" ] || { echo "Missing script dependency: git" >&2; exit 1; } | |
[ -x "$(which pacman)" ] || { echo "Missing script dependency: pacman" >&2; exit 1; } | |
[ -x "$(which makepkg)" ] || { echo "Missing script dependency: makepkg" >&2; exit 1; } | |
[ -x "$(which mkarchiso)" ] || { echo "Missing script dependency: mkarchiso" >&2; exit 1; } | |
# helper | |
quote() { | |
local QUOTED= | |
for ARG in "$@"; do | |
[ "$(printf '%q' "$ARG")" == "$ARG" ] \ | |
&& QUOTED+=" $ARG" \ | |
|| QUOTED+=" ${ARG@Q}" | |
done | |
echo "${QUOTED:1}" | |
} | |
cmd() { | |
echo + "$(quote "$@")" >&2 | |
"$@" | |
} | |
ctee() { | |
local APPEND= | |
[ "$1" != "-a" ] || { APPEND="y"; shift; } | |
local FILE="$1" | |
shift | |
if [ "$APPEND" == "y" ]; then | |
echo + "$(quote "$@") >> $(quote "$FILE")" >&2 | |
"$@" >> "$FILE" | |
else | |
echo + "$(quote "$@") > $(quote "$FILE")" >&2 | |
"$@" > "$FILE" | |
fi | |
} | |
# system setup | |
# make sure that mkarchiso's chroot has internet access in case systemd-resolved isn't used on the host | |
# this will be gone after a reboot and will break if the user switches to a different network | |
echo + "[ -e /run/systemd/resolve/ ]" >&2 | |
if [ ! -e /run/systemd/resolve/ ]; then | |
cmd sudo mkdir -p /run/systemd/resolve/ | |
cmd sudo cp /etc/resolv.conf /run/systemd/resolve/stub-resolv.conf | |
fi | |
# prepare build | |
OUTPUT_DIR="$1" | |
BUILD_DIR="$(mktemp -d -t "$APP_NAME.XXXXXXXXXX")" | |
cmd cd "$BUILD_DIR" | |
cmd cp -R /usr/share/archiso/configs/releng/ ./archiso | |
# change ISO identity | |
cmd sed -i \ | |
-e 's#^iso_name="\(.*\)"$#iso_name="\1-gnome"#g' \ | |
-e 's#^iso_label="\(.*\)"$#iso_label="\1_GNOME"#g' \ | |
-e 's#^iso_publisher="\(.*\)"$#iso_publisher="Daniel Rudolf <https://www.daniel-rudolf.de>"#g' \ | |
-e 's#^iso_application="\(.*\)"$#iso_application="\1 (GNOME)"#g' \ | |
./archiso/profiledef.sh | |
# increase live cow filesystem to 2G (Arch default: 256M) | |
cmd sed -i \ | |
-e 's/^options \(.*\)$/options \1 cow_spacesize=2G/g' \ | |
./archiso/efiboot/loader/entries/01-archiso-x86_64-linux.conf \ | |
./archiso/efiboot/loader/entries/02-archiso-x86_64-speech-linux.conf | |
cmd sed -i \ | |
-e '/^menuentry "Arch Linux/,/^}$/{s/^\( *linux .*\)$/\1 cow_spacesize=2G/g}' \ | |
./archiso/grub/grub.cfg \ | |
./archiso/grub/loopback.cfg | |
cmd sed -i \ | |
-e 's/^APPEND \(.*\)$/APPEND \1 cow_spacesize=2G/g' \ | |
./archiso/syslinux/archiso_sys-linux.cfg | |
# change default keymap | |
ctee ./archiso/airootfs/etc/vconsole.conf \ | |
printf '%s\n' "KEYMAP=de-latin1" "XKBLAYOUT=de" | |
# change default locale | |
ctee ./archiso/airootfs/etc/locale.gen \ | |
printf '%s\n' "de_DE.UTF-8 UTF-8" "en_US.UTF-8 UTF-8" | |
ctee ./archiso/airootfs/etc/locale.conf \ | |
printf '%s\n' "LANG=de_DE.UTF-8" | |
ctee ./archiso/airootfs/etc/pacman.d/hooks/locale-gen.hook \ | |
printf '%s\n' \ | |
"# remove from airootfs!" \ | |
"[Trigger]" \ | |
"Operation = Install" \ | |
"Operation = Upgrade" \ | |
"Type = Package" \ | |
"Target = glibc" \ | |
"" \ | |
"[Action]" \ | |
"Description = Updating locales..." \ | |
"When = PostTransaction" \ | |
"Depends = glibc" \ | |
"Exec = /usr/bin/locale-gen" | |
# change default timezone | |
cmd ln -sf /usr/share/zoneinfo/Europe/Berlin \ | |
./archiso/airootfs/etc/localtime | |
# add the unprivileged 'archiso' user (w/o password), | |
# and add the user to the 'wheel' group | |
# also add sudo and enable it for users in the 'wheel' group | |
ctee -a ./archiso/airootfs/etc/passwd \ | |
printf '%s\n' "archiso:x:1000:1000::/home/archiso:/usr/bin/bash" | |
ctee -a ./archiso/airootfs/etc/shadow \ | |
printf '%s\n' "archiso::14871::::::" | |
ctee ./archiso/airootfs/etc/group \ | |
printf '%s\n' \ | |
"root:x:0:root" \ | |
"wheel:x:998:archiso" \ | |
"archiso:x:1000:" | |
ctee ./archiso/airootfs/etc/gshadow \ | |
printf '%s\n' \ | |
"root:!::" \ | |
"wheel:!*::archiso" \ | |
"archiso:!::" | |
cmd sed -i \ | |
-e '/^file_permissions=($/,/^)$/{s#^)$# \["/etc/gshadow"\]="0:0:400"\n)#g}' \ | |
./archiso/profiledef.sh | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' "sudo" | |
cmd mkdir -p ./archiso/airootfs/etc/sudoers.d/ | |
ctee ./archiso/airootfs/etc/sudoers.d/wheel \ | |
printf '%s\n' "%wheel ALL=(ALL:ALL) ALL" | |
# enable autologin for the 'archiso' user (both for GDM and agetty on tty3) | |
cmd mv ./archiso/airootfs/etc/systemd/system/[email protected]/ \ | |
./archiso/airootfs/etc/systemd/system/[email protected]/ | |
cmd sed -i \ | |
-e 's/--autologin root/--autologin archiso/g' \ | |
./archiso/airootfs/etc/systemd/system/[email protected]/autologin.conf | |
cmd mkdir -p ./archiso/airootfs/etc/gdm/ | |
ctee ./archiso/airootfs/etc/gdm/custom.conf \ | |
printf '%s\n' \ | |
"[daemon]" \ | |
"AutomaticLoginEnable=True" \ | |
"AutomaticLogin=archiso" | |
# update Pacman config | |
# TODO: should rather be done for the pacman.cfg of the image, | |
# however, we don't have a default config to work with yet | |
#cmd sed -i \ | |
# -e 's/#UseSyslog/UseSyslog/g' \ | |
# -e 's/#Color/Color/g' \ | |
# -e 's/#VerbosePkgLists/VerbosePkgLists/g' \ | |
# ./archiso/pacman.conf | |
# add local Pacman repository | |
cmd mkdir -p ./repo/ | |
ctee -a ./archiso/pacman.conf \ | |
printf '%s\n' \ | |
"" \ | |
"[custom]" \ | |
"SigLevel = Optional TrustAll" \ | |
"Server = file://$BUILD_DIR/repo" | |
# build and add yay | |
cmd git clone https://aur.archlinux.org/yay.git | |
cmd makepkg -D ./yay --noconfirm -sr | |
echo + "YAY_PKG=\"\$(find ./yay/ -name 'yay-*-*.pkg.tar.zst' -printf '%f\n')\"" >&2 | |
YAY_PKG="$(find ./yay/ -name 'yay-*-*.pkg.tar.zst' -printf '%f\n')" | |
cmd mv "./yay/$YAY_PKG" "./repo/$YAY_PKG" | |
cmd repo-add ./repo/custom.db.tar.zst "./repo/$YAY_PKG" | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' "yay" | |
ctee ./archiso/airootfs/etc/pacman.d/hooks/yay-setup.hook \ | |
printf '%s\n' \ | |
"# remove from airootfs!" \ | |
"[Trigger]" \ | |
"Operation = Install" \ | |
"Operation = Upgrade" \ | |
"Type = Package" \ | |
"Target = yay" \ | |
"" \ | |
"[Action]" \ | |
"Description = Setting up yay..." \ | |
"When = PostTransaction" \ | |
"Depends = yay" \ | |
"Depends = sudo" \ | |
"Exec = /usr/bin/sudo -u archiso -- /usr/bin/yay -Y --gendb" | |
# add tools required for package building | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"base-devel" \ | |
"git" | |
# add and enable NetworkManager | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' "networkmanager" | |
cmd mkdir -p ./archiso/airootfs/etc/systemd/system/multi-user.target.wants/ | |
cmd ln -sf /usr/lib/systemd/system/NetworkManager.service \ | |
./archiso/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service | |
cmd mkdir -p ./archiso/airootfs/etc/systemd/system/bluetooth.target.wants/ | |
cmd ln -sf /usr/lib/systemd/system/bluetooth.service \ | |
./archiso/airootfs/etc/systemd/system/bluetooth.target.wants/bluetooth.service | |
# add GNOME Shell and enable GDM as display manager | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"gdm" \ | |
"gnome-shell" \ | |
"gnome-menus" \ | |
"gnome-backgrounds" \ | |
"noto-fonts" \ | |
"gnome-control-center" \ | |
"gnome-tweaks" \ | |
"nautilus" | |
cmd ln -sf /usr/lib/systemd/system/gdm.service \ | |
./archiso/airootfs/etc/systemd/system/display-manager.service | |
# build and add gnome-shell-extension-dash-to-dock | |
cmd git clone https://aur.archlinux.org/gnome-shell-extension-dash-to-dock.git | |
cmd makepkg -D ./gnome-shell-extension-dash-to-dock --noconfirm -sr | |
echo + "DTD_PKG=\"\$(find ./gnome-shell-extension-dash-to-dock/ -name 'gnome-shell-extension-dash-to-dock-*-*.pkg.tar.zst' -printf '%f\n')\"" >&2 | |
DTD_PKG="$(find ./gnome-shell-extension-dash-to-dock/ -name 'gnome-shell-extension-dash-to-dock-*-*.pkg.tar.zst' -printf '%f\n')" | |
cmd mv "./gnome-shell-extension-dash-to-dock/$DTD_PKG" "./repo/$DTD_PKG" | |
cmd repo-add ./repo/custom.db.tar.zst "./repo/$DTD_PKG" | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' "gnome-shell-extension-dash-to-dock" | |
# enable the 'Dash to Dock' GNOME extension by default | |
cmd mkdir -p ./archiso/airootfs/etc/dconf/profile/ | |
ctee ./archiso/airootfs/etc/dconf/profile/user \ | |
printf '%s\n' \ | |
"user-db:user" \ | |
"system-db:local" | |
cmd mkdir -p ./archiso/airootfs/etc/dconf/db/local.d/ | |
ctee ./archiso/airootfs/etc/dconf/db/local.d/00-extensions \ | |
printf '%s\n' \ | |
"[org/gnome/shell]" \ | |
"enabled-extensions=['[email protected]']" | |
ctee ./archiso/airootfs/etc/pacman.d/hooks/dconf-update.hook \ | |
printf '%s\n' \ | |
"# remove from airootfs!" \ | |
"[Trigger]" \ | |
"Operation = Install" \ | |
"Operation = Upgrade" \ | |
"Type = Package" \ | |
"Target = dconf" \ | |
"" \ | |
"[Action]" \ | |
"Description = Updating dconf database..." \ | |
"When = PostTransaction" \ | |
"Depends = dconf" \ | |
"Exec = /usr/bin/dconf update" | |
# add GNOME tools | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"gnome-disk-utility" \ | |
"gnome-system-monitor" \ | |
"baobab" \ | |
"gnome-console" \ | |
"gnome-text-editor" \ | |
"meld" \ | |
"evince" \ | |
"loupe" \ | |
"file-roller" \ | |
"gnome-calculator" \ | |
"gnome-connections" | |
# add GNOME Software and Flatpak | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"gnome-software" \ | |
"flatpak" \ | |
"xdg-desktop-portal-gnome" | |
# add Firefox and VLC media player | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"firefox" \ | |
"vlc" | |
# add WireGuard | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"wireguard-tools" \ | |
"openresolv" | |
# add misc command line tools | |
ctee -a ./archiso/packages.x86_64 \ | |
printf '%s\n' \ | |
"bash-completion" \ | |
"htop" \ | |
"iotop" \ | |
"iftop" \ | |
"nethogs" | |
# misc setup | |
cmd mkdir -p ./archiso/airootfs/usr/bin/ | |
cmd ln -sf vim ./archiso/airootfs/usr/bin/vi | |
# run `mkarchiso` | |
cmd sudo mkarchiso -v -o "$OUTPUT_DIR" ./archiso/ | |
# cleanup after successful build | |
cmd sudo rm -rf "$BUILD_DIR" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment