Skip to content

Instantly share code, notes, and snippets.

@simons-public
Last active June 27, 2022 13:20
Show Gist options
  • Save simons-public/e103c57cf5ab4f13928c5e104810af80 to your computer and use it in GitHub Desktop.
Save simons-public/e103c57cf5ab4f13928c5e104810af80 to your computer and use it in GitHub Desktop.

Arch install script

wget archinstall.simons.network -O install.sh
bash install.sh
#!/usr/bin/env bash
#
# Arch linux installation script
#
## Knobs
PASSWORD="password"
DISK="/dev/sda"
ARTIFACTS_DIR="./install-$$"
README="${ARTIFACTS_DIR}/README.md"
SWAP_SIZE=2048
PACKAGES=(bash coreutils dosfstools e2fsprogs
edk2-shell file filesystem findutils gawk
gcc-libs gettext glibc grep gzip iproute2
iputils kbd licenses linux linux-firmware
man-db man-pages mkinitcpio openssh pacman
pciutils procps-ng psmisc sed shadow systemd
sudo tar util-linux xz)
EXTRA_PACKAGES=(base-devel vim git python)
function log () { printf "\e[32m\e[1m -> $@ \e[0m\n"; }
function note () { printf "\e[34m\e[3m NOTE: $@ \e[0m\n"; }
function sanity_check()
{
log "Running sanity check"
# Using EFI:
ls /sys/firmware/efi/efivars &>/dev/null || (echo NOT EFI && exit 1)
# Networking:
ip route | grep default || (echo NO NETWORK && exit 1)
# Disk /dev/sda exists:
test -b ${DISK} || (echo NO DISK && exit 1)
# Check if /mnt/boot is mounted:
test ! -d /mnt/boot || (echo FS MOUNTED && exit 1)
}
function setup_artifacts()
{
log "Setting up installation artifacts"
mkdir -p ${ARTIFACTS_DIR}
cat <<-EOF > ${README}
# Installation Details
EOF
}
function partition_disks()
{
log "Partitioning disk"
cat <<-README >> ${README}
## Partitions
Partition layout stored in partitions-$(basename ${DISK})
${DISK}: gpt Label
${DISK}1: Partition 1, label=ESP, type=ESP (01), size=100M
${DISK}2: Partition 2, label=ROOT, type=Linux (20)
README
sfdisk ${DISK} <<-EOF
label: gpt
device: ${DISK}
unit: sectors
first-lba: 2048
${DISK}1 : name=ESP, start=2048, size=204800, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
${DISK}2 : name=ROOT, start=206848, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
EOF
sfdisk -d ${DISK} > ${ARTIFACTS_DIR}/partitions-$(basename ${DISK})
}
function format_partitions()
{
log "Formatting partitions"
cat <<-README >> ${README}
## Formatting
${DISK}1: fat32, label=ESP
${DISK}2: ext4, label=ROOT
README
# -c: check for bad blocks, -F: fat32, -n LABEL
mkfs.fat -c -F 32 -n ESP ${DISK}1
# -c: check for bad blocks, -L LABEL
mkfs.ext4 -c -F -L ROOT ${DISK}2
}
function mount_partitions()
{
log "Mounting partitions"
mount ${DISK}2 /mnt
mkdir /mnt/boot
mount ${DISK}1 /mnt/boot
}
function update_mirrors()
{
log "Updating mirrorlist"
MIRRORLIST="https://www.archlinux.org/mirrorlist/?country=US&protocol=http&protocol=https&ip_version=4&use_mirror_status=on"
cat <<-README >> ${README}
## Mirrors
Mirrorlist: ${MIRRORLIST}
/etc/pacman.d/mirrorlist
README
curl -L "${MIRRORLIST}" | sed -e 's/^#//' > /etc/pacman.d/mirrorlist
cp /etc/pacman.d/mirrorlist ${ARTIFACTS_DIR}/mirrorlist
}
function install_software()
{
log "Installing software"
cat <<-README >> ${README}
## Packages
Differences from base: -bzip2, -systemd-sysvcompat
Packages: ${PACKAGES[@]}
Extra Packages: ${EXTRA_PACKAGES[@]}
README
pacstrap /mnt ${PACKAGES[@]} ${EXTRA_PACKAGES[@]}
cp /etc/pacman.d/mirrorlist /mnt/etc/pacman.d/mirrorlist
}
function make_swap()
{
log "Making swapfile"
SWAP_FILE="/mnt/var/swapfile"
cat <<-README >> ${README}
## Swap space
Swap file: /mnt/swapfile
README
truncate -s 0 ${SWAP_FILE}
dd if=/dev/zero of=${SWAP_FILE} bs=1M count=${SWAP_SIZE} status=progress
chmod go-r ${SWAP_FILE}
mkswap ${SWAP_FILE}
swapon ${SWAP_FILE}
}
function make_fstab()
{
log "Making /etc/fstab"
cat <<-README >> ${README}
## Fstab
README
genfstab -U /mnt | sed -e 's/^# //' >> ${README}
genfstab -U /mnt >> /mnt/etc/fstab
}
function generate_locales()
{
log "Generating locales"
cat <<-README >> ${README}
## Locale
Locale: en_US.UTF-8, /etc/locale.gen, /etc/locale.conf
README
arch-chroot /mnt /bin/bash <<-EOF
## Generate locales
sed -ie 's/^#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
printf "LANG=en_US.UTF-8\n" > /etc/locale.conf
locale-gen
EOF
}
function make_initramfs()
{
log "Making initramfs"
arch-chroot /mnt /bin/bash <<-EOF
mkinitcpio -p linux
EOF
}
function setup_skel()
{
log "Setting up skel"
cat <<-README >> ${README}
## Skel
Dirs added to /etc/skel:
dev/
.bashrc edits:
PS1
README
mkdir -p /mnt/etc/skel/dev
echo 'PS1="\n\w\n\u@\h-> "' >> /mnt/etc/skel/.bashrc
}
function account_setup()
{
log "Setting up accounts"
cat <<-README >> ${README}
## Accounts
chris:wheel
sudo: wheel, nopasswd
README
arch-chroot /mnt /bin/bash <<-EOF
useradd -m -G wheel chris
printf "root:${PASSWORD}" | chpasswd
printf "chris:${PASSWORD}" | chpasswd
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
EOF
}
function setup_network()
{
log "Setting up network"
cat <<-README >> ${README}
## Network
Wired: systemd-networkd, /etc/systemd/network/wired.network
DHCP: IPv4
DNS: systemd-resolved with mdns enabled
README
cat <<-EOF > /mnt/etc/systemd/network/wired.network
[Match]
Name=en*
[Network]
LinkLocalAddressing=ipv4-fallback
IPv6AcceptRA=no
DHCP=ipv4
MulticastDNS=resolve
[DHCPv4]
UseHostname=false
UseDomains=true
EOF
arch-chroot /mnt /bin/bash <<-EOF
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
systemctl enable systemd-networkd
systemctl enable systemd-resolved
EOF
}
function setup_console()
{
log "Setting up console"
cat <<-README >> ${README}
## Console
Keymap: us, /etc/vconsole.conf
README
cat <<-EOF > /mnt/etc/vconsole.conf
KEYMAP=us
FONT=Lat2-Terminus16
EOF
}
function install_bootloader()
{
log "Installing bootloader"
cat <<-README >> ${README}
## Bootloader
Bootloader: systemd-boot
Pacman hook at: /etc/pacman.d/hooks/100-systemd-boot.hook
Loader entries at: /boot/loader/entries
10-arch.conf
20-arch-fallback.conf
30-shell.conf: relies on edk2-shell package
40-shell-full.conf: relies on edk2-shell package
README
arch-chroot /mnt /bin/bash <<-EOF
bootctl install
EOF
mkdir -p /mnt/etc/pacman.d/hooks
cat <<-EOF > /mnt/etc/pacman.d/hooks/100-systemd-boot.hook
[Trigger]
Type = Package
Operation = Upgrade
Target = systemd
[Action]
Description = Updating systemd-boot
When = PostTransaction
Exec = /usr/bin/bootctl update
EOF
cat <<-EOF > /mnt/boot/loader/entries/10-arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root="LABEL=ROOT" init=/usr/lib/systemd/systemd rw quiet vga=current rd.systemd.show_status=auto rd.udev.log_priority=3
EOF
cat <<-EOF > /mnt/boot/loader/entries/20-arch-fallback.conf
title Arch Linux Fallback
linux /vmlinuz-linux
initrd /initramfs-linux-fallback.img
options root="LABEL=ROOT" init=/usr/lib/systemd/system rw
EOF
cp /mnt/usr/share/edk2-shell/x64/Shell.efi /mnt/boot/
cat <<-EOF > /mnt/boot/loader/entries/30-shell.conf
title EFI Shell
efi /Shell.efi
EOF
cp /mnt/usr/share/edk2-shell/x64/Shell_Full.efi /mnt/boot/
cat <<-EOF > /mnt/boot/loader/entries/40-shell-full.conf
title EFI Shell Full
efi /Shell_Full.efi
EOF
cat <<-EOF >> /mnt/boot/loader/loader.conf
timeout 3
EOF
arch-chroot /mnt /bin/bash <<-EOF
bootctl set-default 10-arch.conf
EOF
}
function enable_first_boot_wizard()
{
log "Enabling first boot wizard"
cat <<-README >> ${README}
## First Boot Wizard
First boot wizard is installed: systemd-firstboot.service
README
FIRSTBOOT_DIR=/mnt/etc/systemd/system/systemd-firstboot.service.d
mkdir -p ${FIRSTBOOT_DIR}
cat <<-EOF > ${FIRSTBOOT_DIR}/override.conf
[Service]
ExecStart=/usr/bin/systemd-firstboot --prompt-timezone --prompt-hostname
EOF
arch-chroot /mnt /bin/bash <<-EOF
systemctl add-wants sysinit.target systemd-firstboot.service
EOF
}
function enable_services()
{
log "Enabling services"
cat <<-README >> ${README}
## Services
SSHD: Enabled
README
arch-chroot /mnt /bin/bash <<-EOF
systemctl enable sshd.service
EOF
}
function modify_agetty()
{
AGETTY_SERVICE_DIR="/mnt/etc/systemd/system/[email protected]"
log "Modifying agetty ExecStart"
cat <<-README >> ${README}
## agetty
Agetty modified to not show hostname and remove noclear the screen
/etc/systemd/system/[email protected]/override.conf
README
mkdir -p ${AGETTY_SERVICE_DIR}
cat <<-EOF > ${AGETTY_SERVICE_DIR}/override.conf
[Service]
ExecStart=
ExecStart=-/sbin/agetty --nohostname -o '-p -- \\u' %I $TERM
EOF
}
function install_issue()
{
log "Installing files into /etc/issue.d"
cat <<-README >> ${README}
## Issue
Issues installed at /etc/issue.d:
10-colors.issue: sets up linux terminal colors
20-warning.issue: shows login warning
30-info.issue: prints information
comment out "/ec" with "//ec" to view 10-colors.issue
README
mkdir -p /mnt/etc/issue.d
cat <<-EOF > /mnt/etc/issue.d/10-colors.issue
\e]P0222222 \e{black} █ Black (Default Background) \e{reset}
\e]P1D23737 \e{red} █ Red \e{reset}
\e]P241d237 \e{green} █ Green \e{reset}
\e]P3D29037 \e{brown} █ Brown (Dark Yellow) \e{reset}
\e]P43794d2 \e{blue} █ Blue \e{reset}
\e]P5B237D2 \e{magenta} █ Magenta (Purple) \e{reset}
\e]P637A2D2 \e{cyan} █ Cyan \e{reset}
\e]P7AAAAAA \e{gray} █ Grey (Default Text) \e{reset}
\e]P8666666 \e{darkgray} █ Dark Gray \e{reset}
\e]P9FF4343 \e{lightred} █ Light Red \e{reset}
\e]PA45FF43 \e{lightgreen} █ Light Green \e{reset}
\e]PBFFB943 \e{yellow} █ Yellow (Light Brown) \e{reset}
\e]PC43B4FF \e{lightblue} █ Light Blue \e{reset}
\e]PDFF43D1 \e{lightmagenta} █ Light Magenta (Pink) \e{reset}
\e]PE43E4FF \e{lightcyan} █ Light Cyan \e{reset}
\e]PFFFFFFF \e{bold} █ Bold \e{reset}
\e{halfbright} Halfbright \e{reset}
\e{reverse} Reverse \e{reset}
\e{blink} Blink \e{reset}
\ec
EOF
cat <<-EOF > /mnt/etc/issue.d/20-warning.issue
\e{lightred} UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
You must have explicit, authorized permission to access or configure this device. Unauthorized
attempts and actions to access or use this system may result in civil and/or criminal penalties.
All activities performed on this device are logged and monitored.
\e{reset}
EOF
cat <<-EOF > /mnt/etc/issue.d/30-info.issue
\e{lightblue} \S (\l) \e{halfbright}v\r [\m]
\e{halfbright} \U on \n (\4)
\e{reset}\e{grey}\d \t \e{lightblue}
EOF
cat <<-EOF > /mnt/etc/issue.sshd
UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
You must have explicit, authorized permission to access or configure this device. Unauthorized
attempts and actions to access or use this system may result in civil and/or criminal penalties.
All activities performed on this device are logged and monitored.
EOF
echo "Banner /etc/issue.sshd" >> /mnt/etc/ssh/sshd_config
}
function install_motd()
{
log "Installing MOTD"
cat <<-README >> ${README}
## MOTD
Motd set to "^[[0m" to reset colors from issue
README
printf "\e[0m" >> /mnt/etc/motd
}
function silence_fsck()
{
FSCK_SERVICE_DIR="/mnt/etc/systemd/system/systemd-fsck-root.service.d"
log "Silencing fsck"
cat <<-README >> ${README}
## Silenced FSCK
Boot fsck silenced using systemd override:
${FSCK_SERVICE_DIR}/override.conf
README
mkdir -p ${FSCK_SERVICE_DIR}
cat <<-EOF > ${FSCK_SERVICE_DIR}/override.conf
[Service]
StandardOutput=journal
StandardError=journal+console
EOF
}
function vconsole_fix()
{
VCONSOLE_SERVICE_DIR="/mnt/etc/systemd/system/systemd-vconsole-setup.service.d/"
log "Fixing systemd-vconsole-setup timing"
cat <<-README >> ${README}
## Fix for vconsole
vconsole starts too early on virtualbox:
${VCONSOLE_SERVICE_DIR}/override.conf
README
mkdir -p ${VCONSOLE_SERVICE_DIR}
cat <<-EOF > ${VCONSOLE_SERVICE_DIR}/override.conf
[Unit]
Wants=systemd-udev-settle.service
After=systemd-udev-settle.service
EOF
}
function setup_symlinks()
{
log "Setting up symlinks"
cat <<-README >> ${README}
## Symlinks
/usr/bin/vi -> /usr/bin/vim
README
ln -s /usr/bin/vim /mnt/usr/bin/vi
}
function save_artifacts()
{
log "Saving installation artifacts to /$(basename ${ARTIFACTS_DIR})"
cp -rv ${ARTIFACTS_DIR} /mnt/
}
function main()
{
set -euf -o pipefail
sanity_check
setup_artifacts
partition_disks
format_partitions
mount_partitions
update_mirrors
install_software
generate_locales
make_swap
make_fstab
make_initramfs
setup_skel
account_setup
setup_network
setup_console
install_bootloader
enable_first_boot_wizard
enable_services
modify_agetty
install_issue
install_motd
silence_fsck
vconsole_fix
setup_symlinks
save_artifacts
}
main
note "Add \'consolefont\' to /etc/mkinitcpio.conf:HOOKS for early fonts"
note "Password is set to \"${PASSWORD}\", change it after rebooting"
# add motd_dir=/etc/motd.d to the end of
# session optional pam_motd.so motd=/etc/motd motd_dir=/etc/motd.d
# in /etc/pam.d/system-login
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment