#!/bin/bash
# ==============================================================================
# SonicDE Artix Linux Installer (Pure Artix Edition)
# Features: No Arch Repos, Native Pacman Install, OpenRC, Multi-Bootloader
# ==============================================================================
# -- 0. Root Check --
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root. Try: sudo ./install.sh"
exit 1
fi
# -- Colors & Variables --
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
MOUNT_POINT="/mnt"
LOG="/tmp/installer.log"
[ -f "$LOG" ] && rm "$LOG"
# -- Helper Functions --
log() { echo -e "${GREEN}[*] $1${NC}" | tee -a "$LOG"; }
err() { echo -e "${RED}[!] $1${NC}" | tee -a "$LOG"; exit 1; }
# -- 1. Pre-Flight Checks --
pre_flight() {
clear
log "Checking environment..."
if ! ping -c 1 google.com &>/dev/null; then
err "No internet connection. Please connect manually."
fi
log "Updating Artix Keyring..."
pacman -Sy --noconfirm artix-keyring
pacman -S --noconfirm dialog git || err "Failed to install dependencies."
}
# -- 2. Configure Artix Repos (Enable Galaxy) --
setup_artix_repos() {
local TARGET_ROOT="$1"
local CONF_PATH="${TARGET_ROOT}/etc/pacman.conf"
log "Configuring Artix Repositories on ${TARGET_ROOT:-Live System}..."
# Ensure [galaxy] is enabled (often needed for community packages)
if ! grep -q "^\[galaxy\]" "$CONF_PATH"; then
# Try to uncomment if it exists
sed -i '/#\[galaxy\]/s/^#//g' "$CONF_PATH" 2>/dev/null
sed -i '/\[galaxy\]/{n;s/^#//}' "$CONF_PATH" 2>/dev/null
# If still missing, append it
if ! grep -q "^\[galaxy\]" "$CONF_PATH"; then
echo -e "\n[galaxy]\nInclude = /etc/pacman.d/mirrorlist" >> "$CONF_PATH"
fi
fi
# Ensure [lib32] is enabled (often needed for Steam/Wine/Gaming)
if ! grep -q "^\[lib32\]" "$CONF_PATH"; then
sed -i '/#\[lib32\]/s/^#//g' "$CONF_PATH" 2>/dev/null
sed -i '/\[lib32\]/{n;s/^#//}' "$CONF_PATH" 2>/dev/null
fi
# Refresh DB
if [ -z "$TARGET_ROOT" ]; then pacman -Sy; fi
}
# -- 3. Menus --
select_menu_options() {
# Drive
OPTIONS=()
while read -r name size model; do
desc="${size}_${model// /_}"
OPTIONS+=("$name" "$desc")
done < <(lsblk -dnp -o NAME,SIZE,MODEL | grep -v 'loop' | grep -v 'sr0')
if [ ${#OPTIONS[@]} -eq 0 ]; then err "No disks found."; fi
DISK=$(dialog --stdout --menu "Select Installation Disk" 15 60 5 "${OPTIONS[@]}") || exit 1
# Partition Method
# Note: Removed tparted because it is an AUR package.
# Without Arch support, we default to standard tools (cfdisk).
METHOD=$(dialog --stdout --menu "Partitioning Method" 12 60 2 \
"Auto" "Automatic Btrfs (Wipe Disk)" \
"Manual" "Manual via cfdisk (Standard)") || exit 1
# Bootloader
BOOTLOADER=$(dialog --stdout --menu "Select Bootloader" 13 60 3 \
"GRUB" "Standard, reliable" \
"rEFInd" "Graphical, auto-detects" \
"Limine" "Modern, simple config") || exit 1
# Timezone
REGIONS=$(find /usr/share/zoneinfo -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | sort)
REGION_ARGS=(); for r in $REGIONS; do REGION_ARGS+=("$r" "-"); done
REGION=$(dialog --stdout --menu "Select Region" 15 40 5 "${REGION_ARGS[@]}") || exit 1
CITIES=$(find "/usr/share/zoneinfo/$REGION" -maxdepth 1 -mindepth 1 -type f -printf "%f\n" | sort)
CITY_ARGS=(); for c in $CITIES; do CITY_ARGS+=("$c" "-"); done
CITY=$(dialog --stdout --menu "Select City" 15 40 10 "${CITY_ARGS[@]}") || exit 1
TIMEZONE="${REGION}/${CITY}"
}
# -- 4. Partitioning --
partition_drive() {
if [ "$METHOD" == "Auto" ]; then
dialog --defaultno --yesno "WARNING: ALL DATA ON $DISK WILL BE ERASED. PROCEED?" 10 60 || exit 1
clear
log "Wiping $DISK..."
sgdisk -Z "$DISK"
sgdisk -n 1:0:+512M -t 1:ef00 -c 1:"EFI" "$DISK"
sgdisk -n 2:0:+4G -t 2:8200 -c 2:"SWAP" "$DISK"
sgdisk -n 3:0:0 -t 3:8300 -c 3:"ROOT" "$DISK"
if [[ "$DISK" == *"nvme"* ]]; then P1="${DISK}p1"; P2="${DISK}p2"; P3="${DISK}p3"; else P1="${DISK}1"; P2="${DISK}2"; P3="${DISK}3"; fi
mkfs.vfat -F32 "$P1"
mkswap "$P2" && swapon "$P2"
mkfs.btrfs -f "$P3"
mount "$P3" "$MOUNT_POINT"
btrfs subvolume create "$MOUNT_POINT/@"
btrfs subvolume create "$MOUNT_POINT/@home"
btrfs subvolume create "$MOUNT_POINT/@snapshots"
btrfs subvolume create "$MOUNT_POINT/@var_log"
umount "$MOUNT_POINT"
mount -o noatime,compress=zstd,subvol=@ "$P3" "$MOUNT_POINT"
mkdir -p "$MOUNT_POINT"/{home,.snapshots,var/log,boot}
mount -o noatime,compress=zstd,subvol=@home "$P3" "$MOUNT_POINT/home"
mount -o noatime,compress=zstd,subvol=@snapshots "$P3" "$MOUNT_POINT/.snapshots"
mount -o noatime,compress=zstd,subvol=@var_log "$P3" "$MOUNT_POINT/var/log"
mount "$P1" "$MOUNT_POINT/boot"
else
clear
log "Launching cfdisk..."
cfdisk "$DISK"
dialog --msgbox "Partitioning complete.\n\nPlease manually mount partitions to /mnt now.\n(Alt+F2 to open terminal, then 'exit' to return)" 10 60
dialog --yesno "Are partitions mounted at /mnt?" 10 60 || exit 1
fi
}
# -- 5. Base Install --
install_base() {
clear
log "Installing Artix Base System..."
# REMOVED: artix-archlinux-support, yaourtix, pikaur
# ADDED: sonicde-meta (Assuming it is in Artix repos as requested)
# We install base system first, SonicDE is installed in config step to catch errors cleanly.
basestrap "$MOUNT_POINT" base base-devel openrc elogind elogind-openrc \
linux linux-firmware networkmanager networkmanager-openrc \
nano git btrfs-progs || err "Basestrap failed."
fstabgen -U "$MOUNT_POINT" >> "$MOUNT_POINT/etc/fstab"
if [ ! -f "$MOUNT_POINT/bin/bash" ]; then
err "Base install failed. /mnt/bin/bash not found."
fi
}
# -- 6. Configure Target (Chroot) --
configure_system() {
HOSTNAME=$(dialog --stdout --inputbox "Enter Hostname:" 10 40 "artixlinux")
USERNAME=$(dialog --stdout --inputbox "Enter Username:" 10 40 "user")
PASSWORD=$(dialog --stdout --passwordbox "Enter Password:" 10 40)
# Prepare Chroot
cp /etc/resolv.conf "$MOUNT_POINT/etc/resolv.conf"
# Generate Script
cat < "$MOUNT_POINT/setup_internal.sh"
#!/bin/bash
set -e
exec < /dev/tty
echo "------------------------------------------------"
echo "Starting Artix Configuration..."
echo "------------------------------------------------"
# 1. System Config
ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime
hwclock --systohc
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "export LANG=en_US.UTF-8" >> /etc/profile
echo "$HOSTNAME" > /etc/hostname
echo "127.0.0.1 localhost" >> /etc/hosts
echo "127.0.1.1 $HOSTNAME.localdomain $HOSTNAME" >> /etc/hosts
# 2. OpenRC Networking
rc-update add NetworkManager default
# 3. Setup Repos (Target)
pacman-key --init
pacman-key --populate artix
# Enable [galaxy] in target if missing
if ! grep -q "^\[galaxy\]" /etc/pacman.conf; then
echo -e "\n[galaxy]\nInclude = /etc/pacman.d/mirrorlist" >> /etc/pacman.conf
fi
pacman -Sy
# 4. User Setup
echo "root:$PASSWORD" | chpasswd
useradd -m -G wheel -s /bin/bash "$USERNAME" || true
echo "$USERNAME:$PASSWORD" | chpasswd
# Allow sudo for wheel
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
# 5. Install SonicDE (NATIVE PACMAN)
echo "------------------------------------------------"
echo "Installing SonicDE from Artix Repos..."
echo "------------------------------------------------"
# We assume sonicde-meta and sddm-openrc are in the enabled repos.
pacman -S --noconfirm sonicde-meta sddm-openrc
# 6. Bootloader
echo "Setting up Bootloader: $BOOTLOADER"
case "$BOOTLOADER" in
"GRUB")
pacman -S --noconfirm grub efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
;;
"rEFInd")
pacman -S --noconfirm refind
refind-install
;;
"Limine")
pacman -S --noconfirm limine
mkdir -p /boot/EFI/BOOT
cp /usr/share/limine/BOOTX64.EFI /boot/EFI/BOOT/BOOTX64.EFI
ROOT_UUID=\$(findmnt / -n -o UUID)
cat < /boot/limine.conf
timeout: 5
/Artix Linux
protocol: linux
kernel_path: boot://2/vmlinuz-linux
kernel_cmdline: root=UUID=\$ROOT_UUID rw rootflags=subvol=@
module_path: boot://2/initramfs-linux.img
/Artix Linux (Fallback)
protocol: linux
kernel_path: boot://2/vmlinuz-linux
kernel_cmdline: root=UUID=\$ROOT_UUID rw rootflags=subvol=@
module_path: boot://2/initramfs-linux-fallback.img
LIMINE
;;
esac
# 7. Services
rc-update add sddm default
rc-update add elogind boot
echo "Configuration Complete."
EOF
chmod +x "$MOUNT_POINT/setup_internal.sh"
clear
log "Entering Artix Chroot..."
artix-chroot "$MOUNT_POINT" /setup_internal.sh
if [ $? -ne 0 ]; then err "Chroot failed! Check errors."; fi
rm "$MOUNT_POINT/setup_internal.sh"
}
# -- Main Execution --
pre_flight
setup_artix_repos ""
select_menu_options
partition_drive
install_base
setup_artix_repos "$MOUNT_POINT"
configure_system
dialog --msgbox "Artix Installation Complete! Rebooting..." 10 60
umount -R "$MOUNT_POINT"
reboot