Skip to content

Instantly share code, notes, and snippets.

@thapakazi
Created January 5, 2026 18:40
Show Gist options
  • Select an option

  • Save thapakazi/f06269fa3933cbe9614bac165c6023d6 to your computer and use it in GitHub Desktop.

Select an option

Save thapakazi/f06269fa3933cbe9614bac165c6023d6 to your computer and use it in GitHub Desktop.
Automated Arch Linux installation for Lima/QEMU (aarch64)
#!/bin/bash
# Automated Arch Linux installation for Lima/QEMU
# Usage: curl -sL <gist-url>/install-arch.sh | bash
#
# Run this inside the Archboot live environment
# Installs to /dev/vda with EFI + root partitions
set -e
# Configuration
DISK="${DISK:-/dev/vda}"
HOSTNAME="${HOSTNAME:-archbox}"
TIMEZONE="${TIMEZONE:-UTC}"
LOCALE="${LOCALE:-en_US.UTF-8}"
ROOT_PASSWORD="${ROOT_PASSWORD:-arch}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}==>${NC} $1"; }
warn() { echo -e "${YELLOW}==> WARNING:${NC} $1"; }
error() { echo -e "${RED}==> ERROR:${NC} $1"; exit 1; }
# Check if running as root
[[ $EUID -ne 0 ]] && error "This script must be run as root"
# Check if disk exists
[[ ! -b "$DISK" ]] && error "Disk $DISK not found"
log "Starting Arch Linux installation to $DISK"
log "Hostname: $HOSTNAME | Timezone: $TIMEZONE"
echo ""
read -p "This will ERASE $DISK. Continue? [y/N] " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
# Step 1: Partition disk
log "Partitioning $DISK..."
parted -s "$DISK" mklabel gpt
parted -s "$DISK" mkpart ESP fat32 1MiB 513MiB
parted -s "$DISK" set 1 esp on
parted -s "$DISK" mkpart root ext4 513MiB 100%
# Wait for partitions
sleep 2
partprobe "$DISK"
# Determine partition names (handles both vda1 and vda-part1 naming)
if [[ -b "${DISK}1" ]]; then
EFI_PART="${DISK}1"
ROOT_PART="${DISK}2"
elif [[ -b "${DISK}p1" ]]; then
EFI_PART="${DISK}p1"
ROOT_PART="${DISK}p2"
else
error "Cannot find partitions on $DISK"
fi
log "EFI partition: $EFI_PART"
log "Root partition: $ROOT_PART"
# Step 2: Format partitions
log "Formatting partitions..."
mkfs.fat -F32 "$EFI_PART"
mkfs.ext4 -F "$ROOT_PART"
# Step 3: Mount partitions
log "Mounting partitions..."
mount "$ROOT_PART" /mnt
mkdir -p /mnt/boot
mount "$EFI_PART" /mnt/boot
# Step 4: Install base system
log "Installing base system (this may take a while)..."
pacstrap -K /mnt \
base \
linux \
linux-firmware \
base-devel \
sudo \
openssh \
cloud-init \
cloud-guest-utils \
vim \
git \
curl \
wget \
htop \
networkmanager
# Step 5: Generate fstab
log "Generating fstab..."
genfstab -U /mnt >> /mnt/etc/fstab
# Step 6: Configure system (chroot)
log "Configuring system..."
cat > /mnt/setup.sh << CHROOT_EOF
#!/bin/bash
set -e
# Timezone
ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime
hwclock --systohc
# Locale
echo "$LOCALE UTF-8" > /etc/locale.gen
locale-gen
echo "LANG=$LOCALE" > /etc/locale.conf
# Hostname
echo "$HOSTNAME" > /etc/hostname
cat > /etc/hosts << EOF
127.0.0.1 localhost
::1 localhost
127.0.1.1 $HOSTNAME.localdomain $HOSTNAME
EOF
# Root password
echo "root:$ROOT_PASSWORD" | chpasswd
# Create arch user for cloud-init fallback
useradd -m -G wheel -s /bin/bash arch || true
echo "arch:arch" | chpasswd
echo "%wheel ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
# Install bootloader (systemd-boot)
bootctl install
# Create boot entry
mkdir -p /boot/loader/entries
cat > /boot/loader/entries/arch.conf << EOF
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=$ROOT_PART rw quiet
EOF
cat > /boot/loader/loader.conf << EOF
default arch.conf
timeout 3
console-mode max
EOF
# Configure cloud-init
mkdir -p /etc/cloud/cloud.cfg.d
cat > /etc/cloud/cloud.cfg.d/99_lima.cfg << EOF
# Lima/QEMU cloud-init config
datasource_list: [ NoCloud, None ]
disable_root: false
ssh_pwauth: true
users:
- default
EOF
# Enable services
systemctl enable sshd
systemctl enable NetworkManager
systemctl enable cloud-init-local.service
systemctl enable cloud-init.service
systemctl enable cloud-config.service
systemctl enable cloud-final.service
# Generate initramfs
mkinitcpio -P
echo "Setup complete inside chroot"
CHROOT_EOF
chmod +x /mnt/setup.sh
arch-chroot /mnt /setup.sh
rm /mnt/setup.sh
# Step 7: Unmount and finish
log "Unmounting..."
umount -R /mnt
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Arch Linux installation complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "Default credentials:"
echo " root:$ROOT_PASSWORD"
echo " arch:arch (sudo enabled)"
echo ""
echo "Run 'poweroff' to shutdown and save the image."
echo "Then update your Lima config to use the new qcow2."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment