arch.sh 14 KB

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