arch.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. # add sublime text source
  43. curl -O https://download.sublimetext.com/sublimehq-pub.gpg && pacman-key --add sublimehq-pub.gpg && pacman-key --lsign-key 8A8F901A && rm sublimehq-pub.gpg
  44. [ $(grep -c "sublime-text" /etc/pacman.conf) -eq 0 ] && echo -e "\n[sublime-text]\nServer = https://download.sublimetext.com/arch/stable/x86_64" | tee -a /etc/pacman.conf
  45. # Core tools
  46. 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"
  47. # install core packages so dependencies exist
  48. pacman -Syu --noconfirm $PACKAGES
  49. # Conditional CPU unicode
  50. [ $(grep -c "Intel" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} intel-ucode"
  51. [ $(grep -c "AMD" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} amd-ucode"
  52. # Conditional battery packages
  53. [ -e /sys/class/power_supply/BAT0 ] && PACKAGES="${PACKAGES} xf86-input-synaptics acpid tlp"
  54. # Storage
  55. PACKAGES="${PACKAGES} btrfs-progs smartmontools usbutils gvfs gvfs-mtp gvfs-afc android-udev parted postgresql transmission-cli python-pip python-setuptools"
  56. # Compression
  57. PACKAGES="${PACKAGES} cryptsetup lzop unzip p7zip xz unrar unace lrzip arj innoextract"
  58. # networking packages
  59. 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"
  60. # programming packages
  61. PACKAGES="${PACKAGES} pkgfile pkgconf bison gcc gcc-libs cmake ccache ncurses lib32-ncurses xmlstarlet jq git mercurial subversion bzr patchelf xdelta3 packer vagrant 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"
  62. # multimedia dependencies
  63. 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 libpng12 lib32-libpng12 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 lxsession-gtk3 yt-dlp wine-staging winetricks fcitx5 fcitx5-mozc fcitx5-configtool fcitx5-gtk fcitx5-qt"
  64. # GUI theme
  65. PACKAGES="${PACKAGES} gnome-themes-extra hicolor-icon-theme"
  66. # GUI dependencies
  67. PACKAGES="${PACKAGES} gtk3 lib32-gtk3 pavucontrol pcmanfm-gtk3 ffmpegthumbnailer tumbler xdg-utils xdg-user-dirs libxcomposite lib32-libxcomposite libxinerama lib32-libxinerama libxslt lib32-libxslt"
  68. # vulkan packages
  69. PACKAGES="${PACKAGES} libva-mesa-driver lib32-libva-mesa-driver lib32-mesa-vdpau vulkan-tools vulkan-icd-loader lib32-vulkan-icd-loader vulkan-headers vulkan-validation-layers lib32-vulkan-validation-layers"
  70. # Sway dependencies
  71. 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"
  72. # fonts
  73. PACKAGES="${PACKAGES} fontconfig ttf-bitstream-vera ttf-droid ttf-dejavu ttf-liberation ttf-hanazono ttf-font-awesome"
  74. # GUI software
  75. PACKAGES="${PACKAGES} xarchiver gparted psensor steam steam-native-runtime gamemode gamescope mangohud lib32-mangohud lib32-gamemode discord mpv mpv-mpris openshot gimp krita obs-studio mednafen mame ppsspp lutris sublime-text evince virt-manager virtualbox virtualbox-host-modules-arch"
  76. # conditional AMD GPU packages
  77. if [ $(lspci | grep -i "vga" | grep -ci "amd") -gt 0 ]; then
  78. PACKAGES="${PACKAGES} xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon mesa-vdpau"
  79. # update modules to load
  80. [ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 amdgpu radeon)/' /etc/mkinitcpio.conf
  81. fi
  82. # conditional Intel GPU packages
  83. if [ $(lspci | grep -i "vga" | grep -ci "intel") -gt 0 ]; then
  84. PACKAGES="${PACKAGES} xf86-video-intel vulkan-intel lib32-vulkan-intel mesa-vdpau"
  85. # update modules to load
  86. [ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 i915)/' /etc/mkinitcpio.conf
  87. fi
  88. # conditional nVidia GPU packages
  89. # @note: untested since 2019; I stopped using nvidia
  90. if [ $(lspci | grep -i "vga" | grep -ci "nvidia") -gt 0 ]; then
  91. PACKAGES="${PACKAGES} nvidia-dkms libglvnd lib32-libglvnd opencl-nvidia lib32-opencl-nvidia xf86-video-nouveau nvidia-utils lib32-nvidia-utils mesa-vdpau nvidia-settings"
  92. # update modules to load
  93. [ $(grep -c "nvidia" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 nvidia nvidia_modeset nvidia_uvm nvidia_drm)/' /etc/mkinitcpio.conf
  94. # automatic mkinitcpio updates in pacman.d
  95. mkdir -p /etc/pacman.d/hooks
  96. 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
  97. fi
  98. # install all packages
  99. pacman -Syu --noconfirm $PACKAGES
  100. # install base configuration files from repository
  101. [ -d /srv/arch-desktop/install ] || git clone https://git.caseydelorme.com/cdelorme/arch-desktop /srv/arch-desktop
  102. rsync -Pav /srv/arch-desktop/install/ /
  103. mkdir -p /etc/skel/{desktop,downloads,public,public/templates,documents,music,pictures,videos,code}
  104. rsync -Pav /etc/skel/ "$(getent passwd root | cut -d: -f6)/"
  105. sed -i "/ssh-add/d" "$(getent passwd root | cut -d: -f6)/.bashrc"
  106. # enable ccache and optimize cores for AUR
  107. sed -i 's/!ccache/ccache/' /etc/makepkg.conf
  108. sed -i 's/^#MAKEFLAGS.*/MAKEFLAGS="-j$(($(nproc) + 1)) -l$(nproc)"/' /etc/makepkg.conf
  109. # @todo: switch to using the main user for these and cloning into code/aur.archlinux.org/
  110. # create a user to install aur packages
  111. export aur_username=$(head /dev/urandom | tr -dc a-z | head -c 13 ; echo '')
  112. useradd -r -m -s /bin/bash $aur_username
  113. echo "${aur_username} ALL= NOPASSWD: /usr/bin/pacman" > /etc/sudoers.d/${aur_username}
  114. # install qview
  115. sudo -u $aur_username git clone https://aur.archlinux.org/qview.git /home/${aur_username}/vimix-cursors
  116. (cd /home/${aur_username}/qview && sudo -u ${aur_username} makepkg -rcsi --noconfirm)
  117. # cmst (for connman UI)
  118. sudo -u $aur_username git clone https://aur.archlinux.org/cmst.git /home/${aur_username}/cmst
  119. (cd /home/${aur_username}/cmst && sudo -u ${aur_username} makepkg -rcsi --noconfirm)
  120. # brave browser
  121. sudo -u $aur_username git clone https://aur.archlinux.org/brave-bin.git /home/${aur_username}/cmst
  122. (cd /home/${aur_username}/brave-bin && sudo -u ${aur_username} makepkg -rcsi --noconfirm)
  123. # install vimix-cursors
  124. sudo -u $aur_username git clone https://aur.archlinux.org/vimix-cursors.git /home/${aur_username}/vimix-cursors
  125. (cd /home/${aur_username}/vimix-cursors && sudo -u ${aur_username} makepkg -rcsi --noconfirm)
  126. # install numix-icon-theme
  127. sudo -u $aur_username git clone https://aur.archlinux.org/numix-icon-theme-git.git /home/${aur_username}/numix-icon-theme-git
  128. (cd /home/${aur_username}/numix-icon-theme-git && sudo -u ${aur_username} makepkg -rcsi --noconfirm)
  129. # cleanup aur user
  130. rm -rf /etc/sudoers.d/${aur_username}
  131. userdel -fr $aur_username
  132. unset $aur_username
  133. # install gifduration
  134. if ! which gifduration &> /dev/null; then
  135. curl -Lfs https://raw.githubusercontent.com/alimony/gifduration-script/master/gifduration.py > /usr/local/bin/gifduration
  136. chmod a+rx /usr/local/bin/gifduration
  137. fi
  138. # install 64bit flash projector
  139. if ! which flashplayer &> /dev/null; then
  140. curl -Lfs "https://fpdownload.macromedia.com/pub/flashplayer/updaters/32/flash_player_sa_linux.x86_64.tar.gz" > /tmp/flash.tar.gz
  141. tar -xf /tmp/flash.tar.gz -C /usr/local/bin flashplayer
  142. fi
  143. # create sudo group and add to sudoers
  144. groupadd -fr sudo
  145. [ ! -f /etc/sudoers.d/sudo ] && echo '%sudo ALL=(ALL) ALL' > /etc/sudoers.d/sudo
  146. # update font cache
  147. fc-cache -fr
  148. # secure ssh by disabling root access and only accepting ssh keys
  149. sed -i "/^#\?PermitRootLogin/d" /etc/ssh/sshd_config
  150. sed -i "/^#\?PasswordAuthentication/d" /etc/ssh/sshd_config
  151. sed -i "/^#\?X11Forwarding/d" /etc/ssh/sshd_config
  152. echo "PermitRootLogin no" >> /etc/ssh/sshd_config
  153. echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
  154. echo "X11Forwarding yes" >> /etc/ssh/sshd_config
  155. # set journald size
  156. sed -i '/^SystemMaxUse/d' /etc/systemd/journald.conf
  157. echo "SystemMaxUse=2G" >> /etc/systemd/journald.conf
  158. # set root password
  159. printf "${root_password}\n${root_password}\n" | passwd
  160. # initialize postgres database
  161. su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"
  162. # create configuration to fix transmission errors
  163. echo "net.core.rmem_max = 4194304" > /etc/sysctl.d/transmission.conf
  164. echo "net.core.wmem_max = 1048576" >> /etc/sysctl.d/transmission.conf
  165. # create user if not exists, else (re)-install dot-files
  166. if ! id $username &> /dev/null; then
  167. useradd -m -s /bin/bash $username
  168. echo "${username}:${password}" | chpasswd -c SHA256
  169. else
  170. [ $EUID -ne 0 ] && rsync -Pav /etc/skel/ "$(getent passwd $username | cut -d: -f6)/"
  171. fi
  172. # add user to standard groups
  173. usermod -aG users,sudo,adm,input,audio,video,disk,storage,lp,vboxusers $username
  174. # generate postgres user and user database
  175. systemctl start postgresql
  176. su postgres -c "cd && createuser -ds $username" 2> /dev/null && su $username -c "cd && createdb"
  177. # load xdg-user-dirs
  178. su $username -c "cd && xdg-user-dirs-update"
  179. update-desktop-database
  180. # generate default (passwordless) ed25519 ssh key if none exists
  181. 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"
  182. # install gvm loading from ~/.bashrc & ~/.bash_profile, and the latest go version
  183. 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"
  184. 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'
  185. su $username -c ". ~/.gvm/scripts/gvm && gvm install go1.21.3 -B && gvm use go1.21.3 --default"
  186. # configure user-space transmission
  187. if [ ! -f "/etc/systemd/system/transmission.service.d/local.conf" ]; then
  188. su $username -c "cd && mkdir -p ~/transmission/{done,incomplete}"
  189. 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'
  190. fi
  191. # symlink shceduled maintenance tasks
  192. #ln -sf /usr/local/bin/system-updates /etc/cron.daily/system-updates
  193. ln -sf /usr/local/bin/disk-maintenance /etc/cron.weekly/disk-maintenance
  194. # symlink override vi to vim
  195. ln -sf /usr/bin/vim /usr/local/bin/vi
  196. # enable services for next reboot
  197. which acpid &> /dev/null && systemctl enable acpid
  198. which tlp &> /dev/null && systemctl enable tlp
  199. systemctl enable postgresql
  200. systemctl enable bluetooth
  201. systemctl enable nftables
  202. systemctl enable libvirtd
  203. systemctl enable dnsmasq
  204. systemctl enable cronie
  205. systemctl enable systemd-timesyncd
  206. systemctl enable sshd
  207. systemctl enable connman
  208. # attempt to enable dhcp on active network devices on reboot
  209. export active_network_device=$(ip addr | awk '/state UP/ {print $2}' | sed 's/.$//')
  210. [ ! -d "/sys/class/net/${active_network_device}/wireless" ] && (systemctl enable dhcpcd@${active_network_device} || echo "failed to enable dhcp service")
  211. # (re)build vmlinux image
  212. mkinitcpio -p linux
  213. # install the bootloader
  214. bootctl install
  215. # create boot loader entry
  216. echo "title arch" > /boot/loader/entries/arch.conf
  217. echo "linux vmlinuz-linux" >> /boot/loader/entries/arch.conf
  218. [ -f /boot/intel-ucode.img ] && echo "initrd /intel-ucode.img" >> /boot/loader/entries/arch.conf
  219. [ -f /boot/amd-ucode.img ] && echo "initrd /amd-ucode.img" >> /boot/loader/entries/arch.conf
  220. echo "initrd /initramfs-linux.img" >> /boot/loader/entries/arch.conf
  221. export boot_options="options root=PARTUUID=$(blkid -s PARTUUID -o value $(mount | grep ' / '|cut -d' ' -f 1)) rw quiet loglevel=3"
  222. [ "$enable_hibernation" = "y" ] && [ -n "$resume_uuid" ] && boot_options="${boot_options} resume=UUID=${resume_uuid}"
  223. [[ $(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"
  224. echo "$boot_options" >> /boot/loader/entries/arch.conf
  225. # set boot loader entry as default
  226. sed -i '/^default/d' /boot/loader/loader.conf
  227. echo "default arch.conf" >> /boot/loader/loader.conf
  228. # remove resolv.conf since connman is wierd ???
  229. rm /etc/resolv.conf
  230. # check boot loader configuration
  231. bootctl status
  232. # cleanup pacman cache to minimize image
  233. yes | pacman -Scc
  234. sync