arch.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #!/bin/bash -e
  2. #
  3. # Author: Casey DeLorme
  4. #
  5. # Description: fully automate installation and config after `arch-chroot`,
  6. # providing the user with a fully configured desktop environment and many
  7. # bells and whistles for developers.
  8. #
  9. # Dependencies: requires `base` and `base-devel` be installed with `pacstrap`,
  10. # and runs as root. Expects `username`, `password`, and `root_password` to be
  11. # supplied.
  12. # verify required variables
  13. while [ -z "$root_password" ]; do read -p "please enter a root password: " -s root_password && echo ""; done
  14. while [ -z "$username" ]; do read -p "please enter your username: " username; done
  15. while [ -z "$password" ]; do read -p "please enter your password: " -s password && echo ""; done
  16. # print all that transpires henceforth
  17. [ -n "$DEBUG" ] && set -x
  18. # initial time configuration
  19. ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
  20. hwclock -w --utc
  21. # setup locale
  22. sed -i "/^en_US.UTF-8/d" /etc/locale.gen
  23. sed -i "/^ja_JP.UTF-8/d" /etc/locale.gen
  24. echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
  25. echo "ja_JP.UTF-8 UTF-8" >> /etc/locale.gen
  26. locale-gen
  27. echo "LANG=en_US.UTF-8" > /etc/locale.conf
  28. # setup hostname
  29. echo "${hostname:-arch}" > /etc/hostname
  30. echo "127.0.0.1 localhost" > /etc/hosts
  31. echo "::1 localhost" >> /etc/hosts
  32. echo "127.0.1.1 $(cat /etc/hostname).localdomain $(cat /etc/hostname)" >> /etc/hosts
  33. # set default virtualconsole font
  34. setfont koi8u_8x16
  35. echo "FONT=koi8u_8x16" > /etc/vconsole.conf
  36. # enable multilib
  37. sed -i "/\[multilib\]/,/Include/"'s/^#//' /etc/pacman.conf
  38. # rebuild gpg keys
  39. rm -rf /etc/pacman.d/gnupg
  40. pacman-key --init
  41. pacman-key --populate archlinux
  42. # Core tools
  43. export PACKAGES="linux linux-headers linux-firmware base-devel mkinitcpio sudo bash-completion man-db tmux gvim dkms dmidecode at bc cronie lm_sensors lshw stress"
  44. # install core packages so dependencies exist
  45. pacman -Syu --noconfirm $PACKAGES
  46. # Conditional CPU unicode
  47. [ $(grep -c "Intel" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} intel-ucode"
  48. [ $(grep -c "AMD" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} amd-ucode"
  49. # Conditional battery packages
  50. [ -e /sys/class/power_supply/BAT0 ] && PACKAGES="${PACKAGES} xf86-input-synaptics acpid tlp"
  51. # Storage
  52. PACKAGES="${PACKAGES} btrfs-progs smartmontools usbutils gvfs gvfs-mtp gvfs-afc android-udev parted postgresql transmission-cli python-pip python-setuptools"
  53. # Compression
  54. PACKAGES="${PACKAGES} cryptsetup lzop unzip p7zip xz unrar unace lrzip arj innoextract"
  55. # networking packages
  56. PACKAGES="${PACKAGES} nftables iptables dnsmasq rsync dhcpcd inetutils net-tools openssh sshfs ntp wget curl wireless_tools bluez bluez-utils oath-toolkit openconnect openvpn ethtool pptpclient connman wpa_supplicant iwd"
  57. # programming packages
  58. PACKAGES="${PACKAGES} pkgfile pkgconf bison gcc gcc-libs cmake ccache ncurses lib32-ncurses xmlstarlet jq git mercurial subversion bzr patchelf xdelta3 packer libvirt qemu qemu-base libguestfs virt-install edk2-ovmf gnutls lib32-gnutls libgpg-error lib32-libgpg-error sqlite lib32-sqlite libgcrypt lib32-libgcrypt ocl-icd lib32-ocl-icd"
  59. # multimedia dependencies
  60. PACKAGES="${PACKAGES} mesa lib32-mesa dbus polkit giflib lib32-giflib mpg123 lib32-mpg123 v4l-utils lib32-v4l-utils lame libwebp libid3tag libvorbis vorbis-tools faac x264 x265 libldap lib32-libldap libpng lib32-libpng libjpeg-turbo lib32-libjpeg-turbo pipewire lib32-pipewire pipewire-jack lib32-pipewire-jack pipewire-alsa pipewire-pulse pipewire-zeroconf wireplumber openal lib32-openal alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib opencl-icd-loader lib32-opencl-icd-loader libva lib32-libva libva-utils gst-plugins-base-libs lib32-gst-plugins-base-libs graphicsmagick imagemagick joyutils evtest libexif ffmpeg yt-dlp wine-staging winetricks fcitx5 fcitx5-mozc fcitx5-configtool fcitx5-gtk fcitx5-qt"
  61. # GUI theme
  62. PACKAGES="${PACKAGES} gnome-themes-extra hicolor-icon-theme"
  63. # GUI dependencies
  64. PACKAGES="${PACKAGES} gtk3 lib32-gtk3 pavucontrol pcmanfm-qt ffmpegthumbnailer tumbler xdg-utils xdg-user-dirs libxcomposite lib32-libxcomposite libxinerama lib32-libxinerama libxslt lib32-libxslt"
  65. # vulkan packages
  66. PACKAGES="${PACKAGES} libva-mesa-driver lib32-libva-mesa-driver vulkan-tools vulkan-icd-loader lib32-vulkan-icd-loader vulkan-headers vulkan-validation-layers lib32-vulkan-validation-layers"
  67. # Sway dependencies
  68. PACKAGES="${PACKAGES} sway swaybg alacritty wofi waybar xorg-xwayland xorg-xlsclients wev qt5-wayland glfw-x11 grim slurp xdg-desktop-portal-wlr libpipewire lib32-libpipewire wl-clipboard brightnessctl playerctl mako libappindicator-gtk3 lib32-libappindicator-gtk3"
  69. # fonts
  70. PACKAGES="${PACKAGES} fontconfig ttf-bitstream-vera ttf-droid ttf-dejavu ttf-liberation ttf-hanazono ttf-jigmo ttf-roboto ttf-sazanami ttf-vlgothic ttf-font-awesome otf-font-awesome"
  71. # GUI software
  72. PACKAGES="${PACKAGES} xarchiver gparted psensor steam gamemode gamescope mangohud lib32-mangohud lib32-gamemode discord mpv mpv-mpris gimp krita obs-studio mednafen mame ppsspp lutris neovim evince virt-manager virtualbox virtualbox-host-modules-arch"
  73. # conditional AMD GPU packages
  74. if [ $(lspci | grep -i "vga" | grep -ci "amd") -gt 0 ]; then
  75. PACKAGES="${PACKAGES} xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon"
  76. # update modules to load
  77. [ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 amdgpu radeon)/' /etc/mkinitcpio.conf
  78. fi
  79. # conditional Intel GPU packages
  80. if [ $(lspci | grep -i "vga" | grep -ci "intel") -gt 0 ]; then
  81. PACKAGES="${PACKAGES} xf86-video-intel vulkan-intel lib32-vulkan-intel mesa-vdpau"
  82. # update modules to load
  83. [ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 i915)/' /etc/mkinitcpio.conf
  84. fi
  85. # conditional nVidia GPU packages
  86. # @note: untested since 2019; I stopped using nvidia
  87. if [ $(lspci | grep -i "vga" | grep -ci "nvidia") -gt 0 ]; then
  88. PACKAGES="${PACKAGES} nvidia-dkms libglvnd lib32-libglvnd opencl-nvidia lib32-opencl-nvidia xf86-video-nouveau nvidia-utils lib32-nvidia-utils mesa-vdpau nvidia-settings"
  89. # update modules to load
  90. [ $(grep -c "nvidia" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 nvidia nvidia_modeset nvidia_uvm nvidia_drm)/' /etc/mkinitcpio.conf
  91. # automatic mkinitcpio updates in pacman.d
  92. mkdir -p /etc/pacman.d/hooks
  93. echo -e "[Trigger]\nOperation=Install\nOperation=Upgrade\nOperation=Remove\nType=Package\nTarget=nvidia\n\n[Action]\nDepends=mkinitcpio\nWhen=PostTransaction\nExec=/usr/bin/mkinitcpio -P" > /etc/pacman.d/hooks/nvidia.hook
  94. fi
  95. # install all packages
  96. pacman -Syu --noconfirm $PACKAGES
  97. # install base configuration files from repository
  98. [ -d /srv/arch-desktop/install ] || git clone https://git.caseydelorme.com/cdelorme/arch-desktop /srv/arch-desktop
  99. rsync -Pav /srv/arch-desktop/install/ /
  100. mkdir -p /etc/skel/{desktop,downloads,public,public/templates,documents,music,pictures,videos,code}
  101. rsync -Pav /etc/skel/ "$(getent passwd root | cut -d: -f6)/"
  102. sed -i "/ssh-add/d" "$(getent passwd root | cut -d: -f6)/.bashrc"
  103. # symlink scheduled maintenance tasks
  104. #ln -sf /usr/local/bin/system-updates /etc/cron.daily/system-updates
  105. ln -sf /usr/local/bin/disk-maintenance /etc/cron.weekly/disk-maintenance
  106. # symlink override vi to vim
  107. ln -sf /usr/bin/vim /usr/local/bin/vi
  108. # enable ccache and optimize cores for AUR
  109. sed -i 's/!ccache/ccache/' /etc/makepkg.conf
  110. sed -i 's/^#MAKEFLAGS.*/MAKEFLAGS="-j$(($(nproc) + 1)) -l$(nproc)"/' /etc/makepkg.conf
  111. # create sudo group and add to sudoers
  112. groupadd -fr sudo
  113. [ ! -f /etc/sudoers.d/sudo ] && echo '%sudo ALL=(ALL) ALL' > /etc/sudoers.d/sudo
  114. # update font cache
  115. fc-cache -fr
  116. # secure ssh by disabling root access and only accepting ssh keys
  117. sed -i "/^#\?PermitRootLogin/d" /etc/ssh/sshd_config
  118. sed -i "/^#\?PasswordAuthentication/d" /etc/ssh/sshd_config
  119. sed -i "/^#\?X11Forwarding/d" /etc/ssh/sshd_config
  120. echo "PermitRootLogin no" >> /etc/ssh/sshd_config
  121. echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
  122. echo "X11Forwarding yes" >> /etc/ssh/sshd_config
  123. # set journald size
  124. sed -i '/^SystemMaxUse/d' /etc/systemd/journald.conf
  125. echo "SystemMaxUse=2G" >> /etc/systemd/journald.conf
  126. # set root password
  127. printf "${root_password}\n${root_password}\n" | passwd
  128. # initialize postgres database
  129. su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"
  130. # create configuration to fix transmission errors
  131. echo "net.core.rmem_max = 4194304" > /etc/sysctl.d/transmission.conf
  132. echo "net.core.wmem_max = 1048576" >> /etc/sysctl.d/transmission.conf
  133. # create user if not exists, else (re)-install dot-files
  134. if ! id $username &> /dev/null; then
  135. useradd -m -s /bin/bash $username
  136. echo "${username}:${password}" | chpasswd -c SHA256
  137. else
  138. [ $EUID -ne 0 ] && rsync -Pav /etc/skel/ "$(getent passwd $username | cut -d: -f6)/"
  139. fi
  140. # add user to standard groups
  141. usermod -aG users,sudo,adm,input,audio,video,disk,storage,lp,vboxusers $username
  142. # generate postgres user and user database
  143. systemctl start postgresql
  144. su postgres -c "cd && createuser -ds $username" 2> /dev/null && su $username -c "cd && createdb"
  145. # load xdg-user-dirs
  146. su $username -c "cd && xdg-user-dirs-update"
  147. update-desktop-database
  148. # generate default (passwordless) ed25519 ssh key if none exists
  149. su $username -c "cd; if [ ! -f ~/.ssh/id_ed25519 ]; then ssh-keygen -q -t ed25519 -N '' -f ~/.ssh/id_ed25519 && cd && chmod 600 ~/.ssh/id_ed25519 && chmod 600 ~/.ssh/id_ed25519.pub; fi"
  150. # install gvm loading from ~/.bashrc & ~/.bash_profile, and the latest go version
  151. su $username -c "if [ ! -d ~/.gvm ]; then GVM_NO_UPDATE_PROFILE=1 bash < <(curl -Ls https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer 2> /dev/null); fi"
  152. su $username -c 'grep "gvm" ~/.bash_profile &> /dev/null || echo -e "\n# load gvm\n[ -s $HOME/.gvm/scripts/gvm ] && . $HOME/.gvm/scripts/gvm" >> ~/.bash_profile'
  153. su $username -c ". ~/.gvm/scripts/gvm && gvm install go1.26.1 -B && gvm use go1.26.1 --default"
  154. # @note: fix stupid fucking cd override in gvm scripts
  155. su $username -c "[ -f ~/.gvm/scripts/env/cd ] && mv ~/.gvm/scripts/env/cd ~/.gvm/scripts/env/cd.bak && touch ~/.gvm/scripts/env/cd"
  156. # configure user-space transmission
  157. if [ ! -f "/etc/systemd/system/transmission.service.d/local.conf" ]; then
  158. su $username -c "cd && mkdir -p ~/transmission/{done,incomplete}"
  159. su $username -c 'cd && tmp=$(mktemp) && jq ".[\"download-dir\"] = \"${HOME}/transmission/done\"" $HOME/.config/transmission-daemon/settings.json | jq ".[\"incomplete-dir\"] = \"${HOME}/transmission/incomplete\"" | jq ".[\"watch-dir\"] = \"$(xdg-user-dir DOWNLOAD)\"" > $tmp && mv $tmp $HOME/.config/transmission-daemon/settings.json'
  160. fi
  161. su $username -c "mkdir -p ~/code/aur.archlinux.org"
  162. export user_home="$(getent passwd $username | cut -d: -f6)/"
  163. # temporarily override sudo for this user
  164. echo "${username} ALL= NOPASSWD: /usr/bin/pacman" > /etc/sudoers.d/${username}
  165. # install qview
  166. sudo -u $username git clone https://aur.archlinux.org/qview.git ${user_home}/aur.archlinux.org/qview
  167. (cd ${user_home}/aur.archlinux.org/qview && sudo -u ${username} makepkg -rcsi --noconfirm)
  168. # cmst (for connman UI)
  169. sudo -u $username git clone https://aur.archlinux.org/cmst.git ${user_home}/aur.archlinux.org/cmst
  170. (cd ${user_home}/aur.archlinux.org/cmst && sudo -u ${username} makepkg -rcsi --noconfirm)
  171. # brave browser (plus override to bypass keyring)
  172. sudo -u $username git clone https://aur.archlinux.org/brave-bin.git ${user_home}/aur.archlinux.org/brave-bin
  173. (cd ${user_home}/aur.archlinux.org/brave-bin && sudo -u ${username} makepkg -rcsi --noconfirm)
  174. [ -f /usr/share/applications/brave-browser.desktop ] && sed -i 's|Exec=brave|Exec=brave --password-store=basic|g' /usr/share/applications/brave-browser.desktop
  175. # install vimix-cursors
  176. sudo -u $username git clone https://aur.archlinux.org/vimix-cursors.git ${user_home}/aur.archlinux.org/vimix-cursors
  177. (cd ${user_home}/aur.archlinux.org/vimix-cursors && sudo -u ${username} makepkg -rcsi --noconfirm)
  178. # install numix-icon-theme
  179. sudo -u $username git clone https://aur.archlinux.org/numix-icon-theme-git.git ${user_home}/aur.archlinux.org/numix-icon-theme-git
  180. (cd ${user_home}/aur.archlinux.org/numix-icon-theme-git && sudo -u ${username} makepkg -rcsi --noconfirm)
  181. # clear sudo override
  182. [ -f /etc/sudoers.d/${username} ] && rm /etc/sudoers.d/${username}
  183. # enable services for next reboot
  184. which acpid &> /dev/null && systemctl enable acpid
  185. which tlp &> /dev/null && systemctl enable tlp
  186. systemctl enable postgresql
  187. systemctl enable bluetooth
  188. systemctl enable nftables
  189. systemctl enable libvirtd
  190. systemctl enable dnsmasq
  191. systemctl enable cronie
  192. systemctl enable systemd-timesyncd
  193. systemctl enable sshd
  194. systemctl enable connman
  195. # attempt to enable dhcp on active network devices on reboot
  196. export active_network_device=$(ip addr | awk '/state UP/ {print $2}' | sed 's/.$//')
  197. [ ! -d "/sys/class/net/${active_network_device}/wireless" ] && (systemctl enable dhcpcd@${active_network_device} || echo "failed to enable dhcp service")
  198. # (re)build vmlinux image
  199. mkinitcpio -p linux
  200. # install the bootloader
  201. bootctl install
  202. # create boot loader entry
  203. echo "title arch" > /boot/loader/entries/arch.conf
  204. echo "linux vmlinuz-linux" >> /boot/loader/entries/arch.conf
  205. [ -f /boot/intel-ucode.img ] && echo "initrd /intel-ucode.img" >> /boot/loader/entries/arch.conf
  206. [ -f /boot/amd-ucode.img ] && echo "initrd /amd-ucode.img" >> /boot/loader/entries/arch.conf
  207. echo "initrd /initramfs-linux.img" >> /boot/loader/entries/arch.conf
  208. export boot_options="options root=PARTUUID=$(blkid -s PARTUUID -o value $(mount | grep ' / '|cut -d' ' -f 1)) rw quiet loglevel=3"
  209. [ "$enable_hibernation" = "y" ] && [ -n "$resume_uuid" ] && boot_options="${boot_options} resume=UUID=${resume_uuid}"
  210. [[ $(lspci | grep -i " vga" | grep -ci " nvidia") -gt 0 && $(grep -c "nvidia" /boot/loader/entires/arch.conf) -eq 0 ]] && boot_options="${boot_options} nvidia-drm.modeset=1"
  211. echo "$boot_options" >> /boot/loader/entries/arch.conf
  212. # set boot loader entry as default
  213. sed -i '/^default/d' /boot/loader/loader.conf
  214. echo "default arch.conf" >> /boot/loader/loader.conf
  215. # remove resolv.conf since connman is wierd ???
  216. rm /etc/resolv.conf
  217. # check boot loader configuration
  218. bootctl status
  219. # cleanup pacman cache to minimize image
  220. yes | pacman -Scc
  221. sync