#!/bin/bash #shellcheck disable=SC2181,SC2086,SC2034 # # archxfce.sh - Arch installation script # SPDX-License-Identifier: MIT # # Minimum disk space: 15G # Recommended disk space: 20G # # 1. boot archlinux--dual.iso # 2. curl -o archxfce.sh # # 3. bash archxfce.sh axprep (extracts 'axprep.sh') # 4. bash archxfce.sh axconf (extracts 'axconf.sh') # # 5. vi axprep.sh axconf.sh (configure) # 6. bash axprep.sh (optional) # 7. arch-chroot /mnt # # 8. cd /root; ./archxfce.sh (in the chroot) # # axprep.sh is handy but not required - the idea is you can replace # the content with your own setup to save on a lot of typing. The # included, commented out code will mount and pacstrap, e.g. # # axconf.sh will be copied to /mnt/root/ with the provided code # in axprep.sh if uncommented. Store your own variable settings in # this file to avoid editing this script. # # archxfce.sh expects everything mounted, pacstrap run and is being # executed from the arch-chroot. (axprep.sh helps with those steps) ###################################################################### ### BOCONF - DO NOT REMOVE OR ALTER THIS LINE ## USER VARS # These must be changed HOSTNAME="myhostname" USERNAME="myusername" # For ${USERNAME} what will be passed to useradd # - 'wheel' will be added to /etc/sudoers # - 'vboxusers' will be added dynamically USER_PGRP="users" USER_SGRP="wheel,storage,power,wireshark" USER_SHLL="/bin/bash" # Set this to true if this is a Virtualbox guest VBOXGUEST=false # Set this to true if this is a Virtualbox host VBOXHOST=false # Various date/time/locale things ARCH_TZ="America/Chicago" ARCH_LA="en_US" ARCH_CP="UTF-8" ARCH_KM="us" ARCH_VF="eurlatgr" # grub mode ('bios' or 'uefi') and boot disk/partitions GRUB_MODE="bios" GRUB_BIOS_DISK="/dev/sda" GRUB_UEFI_PART="/dev/sda1" # Be careful changing this PKG_CORE="grub linux linux-firmware linux-headers linux-lts linux-lts-headers os-prober intel-ucode lvm2 dkms dbus-broker-units" # Can be tuned - includes all video drivers, etc. PKG_XORG="xorg xorg-appres xorg-drivers xorg-xfontsel xorg-xinit xorg-twm xorg-xclock xorg-apps xterm alsa-utils gnu-free-fonts libva-intel-driver mesa ttf-dejavu ttf-liberation xclip" # If VBOXGUEST=true PKG_GVBOX="virtualbox-guest-utils" # If VBOXHOST=true PKG_HVBOX="virtualbox virtualbox-host-dkms" # CLI stuff PKG_CLI="acpi alsa-firmware android-udev base-devel bash-completion bc bind-tools chrony cpio cronie dhclient dmidecode ethtool gdisk git haveged horst iftop iw kexec-tools lshw lsof mailx mtr mutt net-tools nfs-utils nmap ntfs-3g openbsd-netcat openssh parted pkgstats pwgen pyalpm rclone rpcbind rsync screen sharutils strace stunnel sudo sysfsutils tcpdump traceroute tmux unrar unzip usb_modeswitch wget whois wireshark-cli zip zsh zsh-completions" # X Desktop stuff PKG_DWIN="accountsservice lightdm-gtk-greeter gnome-keyring gnome-themes-extra gst-libav gst-plugin-pipewire gst-plugins-good gst-plugins-bad gst-plugins-ugly networkmanager networkmanager-openconnect networkmanager-openvpn networkmanager-pptp networkmanager-vpnc network-manager-applet pipewire pipewire-alsa pipewire-pulse pipewire-v4l2 wireplumber xarchiver xdg-user-dirs xfce4 xfce4-goodies xreader" # GUI stuff PKG_XAPP="audacious audacious-plugins chromium dconf-editor firefox galculator geeqie gimp gjs gucharmap gvfs-afc gvfs-mtp gvfs-smb gvim hunspell-en_US hyphen-en libreoffice-fresh seahorse vlc x11-ssh-askpass wireshark-qt" # Non-essential goodies PKG_EXTRA="7zip android-tools argyllcms aspell axel blueman bluez cadaver clang cmake cmus coin-or-mp colord colord-gtk cups cups-filters cups-pdf cups-pk-helper datamash dialog dos2unix doxygen easytag elinks exfatprogs expac expect extra-cmake-modules fdupes feh ffmpeg figlet foomatic-db foomatic-db-engine foomatic-db-gutenprint-ppds foomatic-db-ppds freeglut freerdp gdb go graphicsmagick gspell gutenprint hspell hwinfo id3v2 inetutils intel-media-sdk iotop jhead jq ladspa libdvdcss libisoburn libmicrohttpd libmp4v2 libvoikko links llvm logrotate lua lynx man-pages mcpp meld mercurial mplayer mpv msr-tools namcap nano ncftp netctl nethogs noto-fonts noto-fonts-cjk numactl nuspell ocl-icd onevpl-intel-gpu opusfile pacman-contrib pacutils perf perl-image-exiftool perl-net-dbus picard qt5-tools qt5-wayland qt5-xmlpatterns restic rtkit rust sdl_image sg3_utils sqlitebrowser subversion syslinux sysstat system-config-printer texlive-bin thunderbird tigervnc time tree tk transmission-gtk ttf-hack ttf-hannom ttf-opensans usbutils vi vorbis-tools weechat words xine-lib zig" # Things that get dragged in by xorg to remove PKG_XDEL="xorg-fonts-100dpi xorg-fonts-75dpi xorg-fonts-alias-100dpi xorg-fonts-alias-75dpi" # Where we'll log all actions (in the chroot) ACTLOG="/root/archxfce.log" # Which file will override all settings (in the chroot) AXCONF="/root/axconf.sh" ### EOCONF - DO NOT REMOVE OR ALTER THIS LINE ###################################################################### ###################################################################### ### BOPREP - DO NOT REMOVE OR ALTER THIS LINE ### ## These are typically done by hand based on partitioning, etc. # ## Helpful Hints # 'mkfs.ext4 -E lazy_itable_init=0,lazy_journal_init=0 ...' # 'parted /dev/sda set 1 boot on' # ## Common # swapon /dev/mapper/vglocal-swap # mount /dev/mapper/vglocal-root /mnt # mkdir /mnt/{boot,home} # mount /dev/mapper/vglocal-home /mnt/home # ## MBR Style # mount /dev/sda1 /mnt/boot # ## UEFI Style # mount /dev/sda2 /mnt/boot # mkdir /mnt/boot/efi # mount /dev/sda1 /mnt/boot/efi # ## Pacstrap # pacstrap /mnt base linux linux-firmware --noprogressbar 2>&1 | tee -a pacstrap.log # genfstab -p -U /mnt >> /mnt/etc/fstab # cp archxfce.sh /mnt/root/ && chmod +x /mnt/root/archxfce.sh # cp pacstrap.log /mnt/root/ # [ -f "axprep.sh" ] && cp axprep.sh /mnt/root/ # [ -f "axconf.sh" ] && cp axconf.sh /mnt/root/ # ## arch-chroot /mnt ### EOPREP - DO NOT REMOVE OR ALTER THIS LINE ### ###################################################################### ###################################################################### ## EXTRACTION # this will save the top part of this script to "axprep.sh" - handy # if you wget this script from a boot ISO and want to save the # pre-prepared stuff for use that is not done on purpose if [[ "$1" == "axprep" ]] && [[ -f "archxfce.sh" ]]; then echo echo "== Creating axprep.sh and exiting ==" echo sed -n '/^### BOPREP/,/^### EOPREP/p' archxfce.sh > axprep.sh exit 2 fi # this will save the top part of this script to "axconf.sh" - handy # if you want to avoid editing this script if [[ "$1" == "axconf" ]] && [[ -f "archxfce.sh" ]]; then echo echo "== Creating axconf.sh and exiting ==" echo sed -n '/^### BOCONF/,/^### EOCONF/p' archxfce.sh > axconf.sh exit 2 fi ###################################################################### ## FUNCTIONS # if a config exists, read it in # shellcheck source=/dev/null [ -f "${AXCONF}" ] && source "${AXCONF}" # trap our signals #shellcheck disable=SC2317 function error_exit { echo "Trapped a kill signal, exiting." exit 99 } trap error_exit SIGHUP SIGINT SIGTERM # handy exit function function myexit() { echo "$1" exit 1 } # run action, log output, return exit code # - passing in 'sed' should be avoided # - functions can only return 0..254 # -- set a global to check as needed _ACTRET=0 function logact() { local ACTION ACTION="$*" ${ACTION} 2>&1 | tee -a ${ACTLOG} _ACTRET=${PIPESTATUS[0]} return ${_ACTRET} } ###################################################################### ## ERROR CHECKING # this will bypass the safety check for /etc/locale.conf (debugging) UNSAFE=false # did you edit this script? if [[ "${HOSTNAME}" == "myhostname" ]] || [[ "${USERNAME}" == "myusername" ]] then myexit "Edit HOSTNAME and USERNAME in this script first - exiting." fi # did you arch-chroot? if [[ -f /mnt/etc/fstab ]]; then myexit "Did you arch-chroot? Found /mnt/etc/fstab - exiting." fi # did you pacstrap? if [[ ! -f /etc/arch-release ]]; then myexit "This doesn't look like Arch, no /etc/arch-release - exiting." fi # is this a live system? if [[ -f /etc/locale.conf ]]; then if [[ ! ${UNSAFE} ]]; then myexit "This looks like a live system, found /etc/locale.conf - exiting." fi fi ###################################################################### ## MISC SETUP # we'll store cookies here -- allows this script to run in stages [[ ! -d /root/.archxfce ]] && mkdir /root/.archxfce # cleaner code below ('#' 70 times) _BAR=$(printf '#%.0s' {1..70}) ###################################################################### ## STAGES ## LOG START ## _DTS=$(date) logact echo -e "\n${_BAR}\n${_BAR}\n## Started: ${_DTS}\n${_BAR}\n${_BAR}" ## STAGE 1 ## logact echo -e "\n${_BAR}\n## Stage 1: Performing initial setup\n${_BAR}" if [[ ! -f /root/.archxfce/stage-1.done ]]; then # Language etc. export LANG="${ARCH_LA}.${ARCH_CP}" echo "${ARCH_LA}.${ARCH_CP} ${ARCH_CP}" >> /etc/locale.gen logact locale-gen cat << EOF > /etc/locale.conf LANG="${ARCH_LA}.${ARCH_CP}" LC_COLLATE="C" EOF cat << EOF > /etc/vconsole.conf KEYMAP="${ARCH_KM}" FONT="${ARCH_VF}" EOF # time/date/hostname logact ln -s /usr/share/zoneinfo/${ARCH_TZ} /etc/localtime logact hwclock --systohc --utc echo ${HOSTNAME} > /etc/hostname cat << EOF >> /etc/hosts 127.0.0.1 localhost ::1 localhost 127.0.1.1 ${HOSTNAME} EOF touch /root/.archxfce/stage-1.done else logact echo " - /root/.archxfce/stage-1.done found, skipping." fi ## STAGE 2 ## logact echo -e "\n${_BAR}\n## Stage 2: Installing core packages\n${_BAR}" if [[ ! -f /root/.archxfce/stage-2.done ]]; then logact pacman -Sy --noconfirm --noprogressbar [[ $? -ne 0 ]] && myexit "pacman error - exiting." logact pacman -S --noconfirm --noprogressbar ${PKG_CORE} [[ $? -ne 0 ]] && myexit "pacman error - exiting." touch /root/.archxfce/stage-2.done else logact echo " - /root/.archxfce/stage-2.done found, skipping." fi # Prevent the screen going blank during install setterm -powersave off -powerdown 0 -blank 0 ## STAGE 3 ## logact echo -e "\n${_BAR}\n## Stage 3: Setting up GRUB and kernels\n${_BAR}" if [[ ! -f /root/.archxfce/stage-3.done ]]; then # add lvm2 hook sed -i.bak -r 's/^HOOKS=(.*)block(.*)/HOOKS=\1block lvm2\2/g' \ /etc/mkinitcpio.conf logact mkinitcpio -p linux logact mkinitcpio -p linux-lts # GRUB our way sed -i.bak -r -e 's/^GRUB_DEFAULT=(.*)/#GRUB_DEFAULT=\1/g' \ -e 's/^GRUB_CMDLINE_LINUX_DEFAULT=(.*)/#GRUB_CMDLINE_LINUX_DEFAULT=\1/g' \ -e 's/^GRUB_SAVEDEFAULT=(.*)/#GRUB_SAVEDEFAULT=\1/g' /etc/default/grub cat << 'EOF' >> /etc/default/grub GRUB_DEFAULT=saved GRUB_CMDLINE_LINUX_DEFAULT="" GRUB_SAVEDEFAULT="true" GRUB_DISABLE_SUBMENU=y EOF if [[ "${GRUB_MODE}" == "bios" ]]; then logact grub-install --target=i386-pc --recheck ${GRUB_BIOS_DISK} elif [[ "${GRUB_MODE}" == "uefi" ]]; then logact pacman -S --noconfirm --noprogressbar dosfstools efibootmgr [[ $? -ne 0 ]] && myexit "pacman error - exiting." logact grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch_grub --recheck --debug logact mkdir -p /boot/efi/EFI/boot logact cp -a /boot/efi/EFI/arch_grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi fi logact grub-mkconfig -o /boot/grub/grub.cfg ROOT_PART=$(grub-probe --target=device /) ROOT_UUID=$(grub-probe --device ${ROOT_PART} --target=fs_uuid) logact grub-set-default "gnulinux-linux-advanced-${ROOT_UUID}" touch /root/.archxfce/stage-3.done else logact echo " - /root/.archxfce/stage-3.done found, skipping." fi ## STAGE 4 ## logact echo -e "\n${_BAR}\n## Stage 4: Installing Xorg and Virtualbox\n${_BAR}" if [[ ! -f /root/.archxfce/stage-4.done ]]; then # base X.org logact pacman -S --noconfirm --noprogressbar ${PKG_XORG} [[ $? -ne 0 ]] && myexit "pacman error - exiting." # Virtualbox Host if [[ $VBOXHOST == true ]]; then logact echo "Installing Virtualbox Host..." logact pacman -S --noconfirm --noprogressbar ${PKG_HVBOX} [[ $? -ne 0 ]] && myexit "pacman error - exiting." cat << 'EOF' > /etc/modules-load.d/vboxhost.conf vboxdrv EOF USER_SGRP="${USER_SGRP},vboxusers" logact systemctl enable dkms.service fi # Virtualbox Guest if [[ $VBOXGUEST == true ]]; then logact echo "Installing Virtualbox Guest..." logact pacman -S --noconfirm --noprogressbar ${PKG_GVBOX} [[ $? -ne 0 ]] && myexit "pacman error - exiting." cat << 'EOF' > /etc/modules-load.d/vboxguest.conf vboxguest vboxsf vboxvideo EOF logact systemctl enable dkms.service logact systemctl enable vboxservice.service fi touch /root/.archxfce/stage-4.done else logact echo " - /root/.archxfce/stage-4.done found, skipping." fi ## STAGE 5 ## logact echo -e "\n${_BAR}\n## Stage 5: Installing all other packages\n${_BAR}" if [[ ! -f /root/.archxfce/stage-5.done ]]; then logact pacman -S --noconfirm --noprogressbar ${PKG_CLI} ${PKG_DWIN} ${PKG_XAPP} [[ $? -ne 0 ]] && myexit "pacman error - exiting." logact pacman -S --noconfirm --noprogressbar ${PKG_EXTRA} [[ $? -ne 0 ]] && myexit "pacman error - exiting." logact pacman -Rnu --noconfirm ${PKG_XDEL} [[ $? -ne 0 ]] && myexit "pacman error - exiting." # clean up a little logact pacman -Sc --noconfirm logact mv /etc/lightdm/lightdm-gtk-greeter.conf{,.bak} cat << 'EOF' > /etc/lightdm/lightdm-gtk-greeter.conf [greeter] theme-name = Adwaita-dark font-name = Sans 12 user-background = false xft-antialias = true xft-hintstyle = none xft-rgba = rgb EOF touch /root/.archxfce/stage-5.done else logact echo " - /root/.archxfce/stage-5.done found, skipping." fi ## STAGE 6 ## logact echo -e "\n${_BAR}\n## Stage 6: User Setup\n${_BAR}" if [[ ! -f /root/.archxfce/stage-6.done ]]; then logact echo -e "\n== Setting root password ==" passwd root logact echo -e "\n== Adding user ${USERNAME} ==" logact useradd -m -g ${USER_PGRP} -G ${USER_SGRP} -s ${USER_SHLL} ${USERNAME} passwd ${USERNAME} echo '%wheel ALL=(ALL) ALL' >> /etc/sudoers ## AUR setup as a user later if [[ ! -f "/home/${USERNAME}/aur_setup.sh" ]]; then logact echo -e "\n== Creating /home/${USERNAME}/aur_setup.sh ==" cat << 'EOF' > /home/${USERNAME}/aur_setup.sh mkdir ~/aurhub cd ~/aurhub/ git clone https://aur.archlinux.org/pikaur.git cd pikaur sudo pacman -Sy makepkg -fsri ## random AUR things - uncomment/edit as desired #PKG_AUR="bluez-firmware bvi downgrade gkrellm-themes gnome-icon-theme gnome-icon-theme-symbolic networkmanager-dispatcher-chrony pandoc-bin shellcheck-bin simplescreenrecorder smem" #pikaur -S --noconfirm ${PKG_AUR} EOF chown ${USERNAME}:users /home/${USERNAME}/aur_setup.sh fi touch /root/.archxfce/stage-6.done else logact echo " - /root/.archxfce/stage-6.done found, skipping." fi ## STAGE 7 ## logact echo -e "\n${_BAR}\n## Stage 7: Enabling system services\n${_BAR}" if [[ ! -f /root/.archxfce/stage-7.done ]]; then # firewall rules, port 22 open by default rm -f /etc/iptables/*.rules cat << 'EOF' > /etc/iptables/iptables.rules *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT EOF cat << 'EOF' > /etc/iptables/ip6tables.rules *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -j REJECT --reject-with icmp6-adm-prohibited -A FORWARD -j REJECT --reject-with icmp6-adm-prohibited COMMIT EOF # keep the journal small mkdir -p /etc/systemd/journald.conf.d cat << 'EOF' > /etc/systemd/journald.conf.d/logtime.conf [Journal] MaxRetentionSec=1week SystemMaxUse=50M EOF # kill user processes on logout mkdir -p /etc/systemd/logind.conf.d cat << 'EOF' > /etc/systemd/logind.conf.d/killprocs.conf [Login] KillUserProcesses=yes EOF # don't save coredumps mkdir -p /etc/systemd/coredump.conf.d cat << 'EOF' > /etc/systemd/coredump.conf.d/storage.conf [Coredump] Storage=none ProcessSizeMax=0 EOF echo 'kernel.core_pattern=|/bin/false' > /etc/sysctl.d/50-coredump.conf # allow strace of own processes echo 'kernel.yama.ptrace_scope=0' > /etc/sysctl.d/10-ptrace.conf logact systemctl enable lightdm.service logact systemctl enable NetworkManager.service logact systemctl enable bluetooth.service logact systemctl enable cronie.service logact systemctl enable iptables.service logact systemctl enable ip6tables.service logact systemctl enable sshd.service logact systemctl enable chronyd.service logact systemctl enable accounts-daemon.service logact systemctl enable cups.service logact systemctl enable sysstat.service logact systemctl enable haveged.service touch /root/.archxfce/stage-7.done else logact echo " - /root/.archxfce/stage-7.done found, skipping." fi ## LOG FINISH ## _DTS=$(date) logact echo -e "\n${_BAR}\n${_BAR}\n## Finished: ${_DTS}\n${_BAR}\n${_BAR}" logact echo -e "Typical next steps:\n" logact echo "# alsamixer (change base levels to ~50%)" logact echo "# vim /etc/chrony.conf to set offline mode (laptop)" logact echo "# vim /etc/mkinitcpio.conf (add resume hook for laptop)" logact echo "# vim /etc/fstab (add discard for SSD)" logact echo "# systemctl enable fstrim.timer (SSD)" logact echo "# systemctl enable cpupower.service (laptop)" logact echo -e "\n# exit (the chroot)\n# umount -R /mnt\n# reboot\n" exit 0