void_install.sh 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. #!/bin/env bash
  2. #############################################################################
  3. # ██╗ ██╗ ██████╗ ██╗██████╗ ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ███████╗██████╗
  4. # ██║ ██║██╔═══██╗██║██╔══██╗ ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ██╔════╝██╔══██╗
  5. # ██║ ██║██║ ██║██║██║ ██║ ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ █████╗ ██████╔╝
  6. # ╚██╗ ██╔╝██║ ██║██║██║ ██║ ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ██╔══╝ ██╔══██╗
  7. # ╚████╔╝ ╚██████╔╝██║██████╔╝ ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗███████╗██║ ██║
  8. # ╚═══╝ ╚═════╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝
  9. #########################################################################################################
  10. # Writen: Bzz
  11. # Link: https://notabug.org/bzz/void_installer/src/main/void_install.sh
  12. # License: BSD
  13. # About: Script for installing Void Linux. Support LVM, LUKS. ROOTFS metod instalation OS.
  14. # Dependencies: xz, curl
  15. # Information:
  16. # [-]=waiting
  17. # [+]=successful
  18. # [!]=warning
  19. # [*]=info
  20. # [?]=aksing
  21. #########################################################################################################
  22. # Colors
  23. # cl_black=$'\e[30m'
  24. # cl_red=$'\e[31m'
  25. # cl_green=$'\e[32m'
  26. # cl_yellow=$'\e[33m'
  27. # cl_blue=$'\e[34m'
  28. # cl_magenta=$'\e[35m'
  29. # cl_cyan=$'\e[36m'
  30. # cl_white=$'\e[37m'
  31. # cl_bright=$'\e[1m'
  32. # cl_normal=$'\e[0m'
  33. cl_red=$'\e[31m'
  34. cl_green=$'\e[32m'
  35. cl_blue=$'\e[34m'
  36. cl_normal=$'\e[0m'
  37. # Environment
  38. luks_name="voidpc"
  39. lvm_name="voidpc"
  40. fs_type="ext4"
  41. sys_hostname="voidpc"
  42. sys_language="en_US.UTF-8"
  43. sys_locale="en_US.UTF-8 UTF-8"
  44. user_groups="wheel,floppy,cdrom,optical,audio,video,kvm"
  45. grub_discards="rd.luks.allow-discards"
  46. rootfs_link="https://repo-default.voidlinux.org/live/current/void-x86_64-ROOTFS-20240314.tar.xz"
  47. clear
  48. # Check is script running by root user
  49. if [ "$(id -u)" != 0 ]; then
  50. printf "%s[!] Script needs to run as root%s\n" "${cl_red}" "${cl_normal}"
  51. exit 2
  52. fi
  53. # Check dependencies package curl
  54. if ! [ -x "$(command -v curl)" ]; then
  55. printf "%s[!] Program curl is not installed!%s\n" "${cl_red}" "${cl_normal}"
  56. exit 1
  57. fi
  58. # Check dependencies package xz
  59. if ! [ -x "$(command -v xz)" ]; then
  60. printf "%s[!] Program xz is not installed!%s\n" "${cl_red}" "${cl_normal}"
  61. exit 1
  62. fi
  63. printf "%s######################%s\n" "${cl_blue}" "${cl_normal}"
  64. printf "%s# Install Void Linux #%s\n" "${cl_blue}" "${cl_normal}"
  65. printf "%s######################%s\n" "${cl_blue}" "${cl_normal}"
  66. printf "%s================================%s\n" "${cl_green}" "${cl_normal}"
  67. printf "%s[*] Selecting disk (DEVICE:SIZE)%s\n" "${cl_green}" "${cl_normal}"
  68. printf "%s================================%s\n" "${cl_green}" "${cl_normal}"
  69. # Prompt user to select disk for installation
  70. run_dev=$(lsblk -psln -o NAME "$(df --output=source / | sed 1d)" | tail -n1)
  71. PS3="[?] Select disk for installation: "
  72. # select _ln in $(lsblk -pdno NAME,SIZE | sed 's/ \+/:/g' | grep -v "${run_dev}"); do
  73. select _ln in $(lsblk -pdno NAME,SIZE | sed 's/ \+/:/g'); do
  74. if [ -z "${_ln}" ]; then
  75. printf "%s[!] Wrong selection%s\n" "${cl_red}" "${cl_normal}"
  76. exit 1
  77. fi
  78. printf "[+] Selected disk: <%s>\n" "${_ln}"
  79. inst_dev=$(echo "${_ln}" | cut -d':' -f1)
  80. break
  81. done
  82. # Unmount all filesystem in /mnt folder
  83. if grep -q " /mnt " /proc/mounts; then
  84. if ! umount -qR /mnt; then
  85. printf "%s[!] Erorr unmounting folder /mnt %s\n" "${cl_red}" "${cl_normal}"
  86. exit 1
  87. fi
  88. fi
  89. # Check if LVM is active
  90. _dev=$(lsblk -pnlo NAME,FSTYPE "${inst_dev}" | grep LVM2 | awk '{ print$1 }')
  91. if [ -n "${_dev}" ]; then
  92. if lvscan --devices "${_dev}" | grep -q ACTIVE; then
  93. _vg=$(pvscan --listvg "${_dev}" | awk '{ print$2}')
  94. vgchange -qan "${_vg}"
  95. fi
  96. fi
  97. # Check if LUKS is open
  98. _name=$(lsblk -nlo NAME,TYPE "${inst_dev}" | grep "crypt$" | awk '{ print$1}')
  99. if [ -n "${_name}" ]; then
  100. if cryptsetup status "${_name}" | grep -q "is active"; then
  101. cryptsetup close "${_name}"
  102. fi
  103. fi
  104. # Check if luks_name is open
  105. if cryptsetup status "${luks_name}" | grep -q "is active"; then
  106. printf "%s[!] LUKS volume <%s> is active%s\n" "${cl_red}" "${luks_name}" "${cl_normal}"
  107. exit 1
  108. fi
  109. # Check if installed device is mounted
  110. for _dev in $(lsblk -pnlo NAME "${inst_dev}"); do
  111. if grep -q "${_dev}" /proc/mounts; then
  112. printf "%s[!] Device <%s> is mounted%s\n" "${cl_red}" "${_dev}" "${cl_normal}"
  113. exit 1
  114. fi
  115. done
  116. # Promt for script continuation
  117. read -rp "[?] Install to device <${inst_dev}>: (y/n) " _key
  118. if [ "${_key}" != "y" ]; then
  119. printf "%s[!] Aborted!%s\n" "${cl_red}" "${cl_normal}"
  120. exit 1
  121. fi
  122. # Promt separete /boot dir
  123. read -rp "[?] Folder /boot on separate partition: (y/n) " _key
  124. if [ "${_key}" == "y" ]; then
  125. inst_boot="yes"
  126. fi
  127. # Wipe disk
  128. wipefs -aqf "${inst_dev}" >/dev/null &&
  129. printf "[+] Wipe disk %s\n" "${inst_dev}"
  130. # Format disklabel as DOS, create partition for LUKS
  131. if [ "${inst_boot}" == "yes" ]; then
  132. printf 'label: dos\n, 1G, L, *\n, , L\n' | sfdisk -q "${inst_dev}" &&
  133. printf "[+] Create disklabel type <DOS> and partition\n"
  134. inst_dev_boot=$(lsblk -pnlo NAME "${inst_dev}" | sed -n 2p)
  135. inst_dev_pool=$(lsblk -pnlo NAME "${inst_dev}" | sed -n 3p)
  136. else
  137. printf 'label: dos\n, , L, *\n' | sfdisk -q "${inst_dev}" &&
  138. printf "[+] Create disklabel type <DOS> and partition\n"
  139. inst_dev_pool=$(lsblk -pnlo NAME "${inst_dev}" | sed 1d)
  140. fi
  141. printf "%s=======================%s\n" "${cl_green}" "${cl_normal}"
  142. printf "%s[*] Users and passwords%s\n" "${cl_green}" "${cl_normal}"
  143. printf "%s=======================%s\n" "${cl_green}" "${cl_normal}"
  144. # Grab informations about users and passwords
  145. read -rsp "[?] Password for user <root>: " root_pass
  146. printf "\n"
  147. read -rp "[?] Non-root user: " user_name
  148. read -rsp "[?] Password for user <${user_name}>: " user_pass
  149. printf "\n"
  150. printf "%s========================%s\n" "${cl_green}" "${cl_normal}"
  151. printf "%s[*] Encrypting partition%s\n" "${cl_green}" "${cl_normal}"
  152. printf "%s========================%s\n" "${cl_green}" "${cl_normal}"
  153. read -rsp "[?] Password for encrypting device: " luks_pass
  154. printf "\n"
  155. printf "[-] Encrypting partition, wait... "
  156. # Create LUKS encrypted partition
  157. if [ "${inst_boot}" == "yes" ]; then
  158. # Create LUKS type 2
  159. if echo "${luks_pass}" | cryptsetup -q luksFormat "${inst_dev_pool}"; then
  160. printf "OK!\n"
  161. else
  162. printf "%s[!] ERROR%s\n" "${cl_red}" "${cl_normal}"
  163. exit 1
  164. fi
  165. else
  166. # Create LUKS type 1, for GRUB support
  167. if echo "${luks_pass}" | cryptsetup -q --type luks1 luksFormat "${inst_dev_pool}"; then
  168. printf "OK!\n"
  169. else
  170. printf "%s[!] ERROR%s\n" "${cl_red}" "${cl_normal}"
  171. exit 1
  172. fi
  173. fi
  174. # Open encrypted partition
  175. printf "[-] Opening volume to </dev/mapper/%s>... " "${luks_name}"
  176. if echo "${luks_pass}" | cryptsetup open "${inst_dev_pool}" "${luks_name}"; then
  177. printf "OK!\n"
  178. else
  179. printf "%s[!] ERROR%s\n" "${cl_red}" "${cl_normal}"
  180. exit 1
  181. fi
  182. printf "%s=================================%s\n" "${cl_green}" "${cl_normal}"
  183. printf "%s[*] Creating LVM and file systems%s\n" "${cl_green}" "${cl_normal}"
  184. printf "%s=================================%s\n" "${cl_green}" "${cl_normal}"
  185. # Create LVM in encrypted partition, and create file systems
  186. pvcreate /dev/mapper/${luks_name} >/dev/null &&
  187. printf "[+] PV </dev/mapper/%s> successfully created\n" "${luks_name}"
  188. vgcreate ${lvm_name} /dev/mapper/${luks_name} >/dev/null &&
  189. printf "[+] VG <%s> successfully created\n" "${lvm_name}"
  190. # Reading size for LVs
  191. inst_dev_size=$(lsblk -pdno SIZE "${inst_dev_pool}" | sed 's/ \+//g')
  192. printf "[+] Max size for LV partition - <%s>\n" "${inst_dev_size}"
  193. read -rp "[?] Size{M,G,T,P} for LV-root (empty - all space): " lvm_root_size
  194. # Check if size is correct
  195. if [ -n "${lvm_root_size}" ]; then
  196. echo "${lvm_root_size}" | grep -qE "^[0-9]+(\.[0-9])?[MGTP]$"
  197. if [ $? == 1 ]; then
  198. printf "%s[!] Not correct size%s\n" "${cl_red}" "${cl_normal}"
  199. exit 1
  200. fi
  201. # Creating LVs
  202. lvcreate --name root -L "${lvm_root_size}" "${lvm_name}" >/dev/null &&
  203. printf "[+] Logical volume <root> created\n"
  204. lvcreate --name home -l 100%FREE ${lvm_name} >/dev/null &&
  205. printf "[+] Logical volume <home> created\n"
  206. # Creating FS for LVs
  207. printf "[-] Creating FS for LV root, wait... "
  208. mkfs.${fs_type} -qL root /dev/${lvm_name}/root && printf "OK!\n"
  209. printf "[-] Creating FS for LV home, wait... "
  210. mkfs.${fs_type} -qL home /dev/${lvm_name}/home && printf "OK!\n"
  211. else
  212. lvcreate --name root -l 100%FREE ${lvm_name} >/dev/null &&
  213. printf "[+] Logical volume <root> created\n"
  214. printf "[-] Creating FS for LV root, wait... "
  215. mkfs.${fs_type} -qL root /dev/${lvm_name}/root && printf "OK!\n"
  216. fi
  217. # Creating FS for /boot
  218. if [ "${inst_boot}" == "yes" ]; then
  219. printf "[-] Creating FS for boot, wait... "
  220. mkfs.ext2 -qFL boot "${inst_dev_boot}" && printf "OK!\n"
  221. fi
  222. printf "%s========================%s\n" "${cl_green}" "${cl_normal}"
  223. printf "%s[*] Mounting FileSystems%s\n" "${cl_green}" "${cl_normal}"
  224. printf "%s========================%s\n" "${cl_green}" "${cl_normal}"
  225. # Mount LVM's
  226. if [ -n "${lvm_root_size}" ]; then
  227. mount /dev/${lvm_name}/root /mnt &&
  228. printf "[+] Mount LV root to /mnt\n"
  229. mkdir /mnt/home
  230. mount /dev/${lvm_name}/home /mnt/home &&
  231. printf "[+] Mount LV home to /mnt/home\n"
  232. else
  233. mount /dev/${lvm_name}/root /mnt &&
  234. printf "[+] Mount LV root to /mnt\n"
  235. fi
  236. # Mount boot
  237. if [ "${inst_boot}" == "yes" ]; then
  238. mkdir /mnt/boot
  239. mount "${inst_dev_boot}" /mnt/boot &&
  240. printf "[+] Mount boot to /mnt/boot\n"
  241. fi
  242. # Mount pseudo FS's
  243. for _fs in dev proc sys; do
  244. mkdir /mnt/${_fs}
  245. mount --rbind "/${_fs}" "/mnt/${_fs}"
  246. mount --make-rslave "/mnt/${_fs}"
  247. printf "[+] Mount /%s to /mnt/%s\n" "${_fs}" "${_fs}"
  248. done
  249. printf "%s====================%s\n" "${cl_green}" "${cl_normal}"
  250. printf "%s[*] ROOTFS preparing%s\n" "${cl_green}" "${cl_normal}"
  251. printf "%s====================%s\n" "${cl_green}" "${cl_normal}"
  252. # Download and install base packages
  253. printf "[-] Downloading rootfs tarball, wait... "
  254. if curl -s -o void.tar.xz ${rootfs_link}; then
  255. printf "OK!\n"
  256. else
  257. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  258. exit 1
  259. fi
  260. printf "[-] Extract files from archive, wait... "
  261. if tar xf void.tar.xz -C /mnt; then
  262. printf "OK!\n"
  263. else
  264. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  265. exit 1
  266. fi
  267. # Remove ROOTFS file
  268. rm -f void.tar.xz >/dev/null
  269. # Copy the DNS configuration
  270. mkdir -p /mnt/etc
  271. cp /etc/resolv.conf /mnt/etc/
  272. printf "%s=================================%s\n" "${cl_green}" "${cl_normal}"
  273. printf "%s[*] Chroot: install and configure%s\n" "${cl_green}" "${cl_normal}"
  274. printf "%s=================================%s\n" "${cl_green}" "${cl_normal}"
  275. # Change ownership and permissions of root directory
  276. chroot /mnt chown root:root /
  277. chroot /mnt chmod 755 /
  278. # Installing base system
  279. printf "[-] Syncing system and update xbps, wait..."
  280. if chroot /mnt xbps-install -Suy xbps >/dev/null; then
  281. printf "OK\n"
  282. else
  283. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  284. exit 1
  285. fi
  286. printf "[-] Updating system, wait..."
  287. if chroot /mnt xbps-install -uy >/dev/null; then
  288. printf "OK\n"
  289. else
  290. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  291. exit 1
  292. fi
  293. printf "[-] Installing base system, wait..."
  294. if chroot /mnt xbps-install -y base-system lvm2 cryptsetup grub >/dev/null; then
  295. printf "OK\n"
  296. else
  297. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  298. exit 1
  299. fi
  300. printf "[-] Removing package base-voidstrap, wait... "
  301. if chroot /mnt xbps-remove -y base-voidstrap >/dev/null; then
  302. printf "OK\n"
  303. else
  304. printf "%s[!] ERROR!!%s\n" "${cl_red}" "${cl_normal}"
  305. fi
  306. # Add and set passwords for users
  307. printf "[+] Set password for user <root>\n"
  308. printf "%s\n%s" "${root_pass}" "${root_pass}" | passwd -R /mnt root
  309. printf "[-] Adding user <%s>... " "${user_name}"
  310. chroot /mnt useradd "${user_name}" && printf "OK!\n"
  311. printf "[-] Modifying user <%s>... " "${user_name}"
  312. chroot /mnt usermod -aG "${user_groups}" "${user_name}" && printf "OK!\n"
  313. printf "[+] Set password for user <%s>\n" "${user_name}"
  314. printf "%s\n%s" "${user_pass}" "${user_pass}" | passwd -R /mnt "${user_name}"
  315. # Set hostname and language/locale
  316. echo "${sys_hostname}" >/mnt/etc/hostname
  317. printf "[+] Set hostname <%s>\n" "${sys_hostname}"
  318. echo "LANG=${sys_language}" >/mnt/etc/locale.conf
  319. printf "[+] Set language <%s>\n" "${sys_language}"
  320. # libc-locales are only applicable for glibc installations
  321. echo "${sys_locale}" >>/mnt/etc/default/libc-locales
  322. printf "[-] Reconfiguring locale to <%s>, wait... " "${sys_locale}"
  323. chroot /mnt xbps-reconfigure -f glibc-locales >/dev/null && printf "OK!\n"
  324. # Modify file /etc/fstab in chroot
  325. if [ "${inst_boot}" == "yes" ]; then
  326. boot_uuid="UUID=\"$(lsblk -no UUID "${inst_dev_boot}")\""
  327. sed -n "s|${inst_dev_boot}|${boot_uuid}|; s|/mnt/boot|/boot|p" /proc/mounts >> \
  328. /mnt/etc/fstab
  329. fi
  330. grep "/dev/mapper/${lvm_name}" /proc/mounts |
  331. awk '$2 == "/mnt" { $2 = "/" } $2 == "/mnt/home" { $2 = "/home" } 1' >> \
  332. /mnt/etc/fstab
  333. printf "[+] Update /etc/fstab\n"
  334. # Enable LUKS in GRUB
  335. echo "GRUB_ENABLE_CRYPTODISK=y" >>/mnt/etc/default/grub
  336. luks_uuid=$(lsblk -ndo UUID "${inst_dev_pool}")
  337. kernel_params="rd.lvm.vg=${lvm_name} rd.luks.uuid=$luks_uuid ${grub_discards}"
  338. sed -i "s/\(GRUB_CMDLINE_LINUX_DEFAULT=\"\)/\1${kernel_params} /" \
  339. /mnt/etc/default/grub
  340. printf "[+] Enable LUKS in GRUB\n"
  341. # Generate keyfile to automatically unlock the encrypted volume on boot.
  342. dd bs=1 count=64 if=/dev/urandom of=/mnt/root/volume.key status=none
  343. echo "${luks_pass}" | cryptsetup -q luksAddKey "${inst_dev_pool}" /mnt/root/volume.key
  344. # Change the permissions to protect generated the keyfile
  345. chmod 000 /mnt/root/volume.key
  346. chmod -R g-rwx,o-rwx /mnt/root/volume.key
  347. printf "%s\tUUID=%s\t/root/volume.key\tluks\n" "${luks_name}" "${luks_uuid}" >> \
  348. /mnt/etc/crypttab
  349. # Configure for dracut
  350. printf "install_items+=\" /root/volume.key /etc/crypttab \"\n" > \
  351. /mnt/etc/dracut.conf.d/10-crypt.conf
  352. # Install GRUB bootloader
  353. printf "[-] Installing GRUB to <%s>, wait...\n" "${inst_dev}"
  354. chroot /mnt grub-install "${inst_dev}" >/dev/null
  355. # Ensure an initramfs is generated
  356. printf "[-] Reconfigure system, wait...\n"
  357. chroot /mnt xbps-reconfigure -fa >/dev/null
  358. printf "[+] Done!\n"
  359. printf "%s=======================%s\n" "${cl_green}" "${cl_normal}"
  360. printf "%s[*] Swap file configure%s\n" "${cl_green}" "${cl_normal}"
  361. printf "%s=======================%s\n" "${cl_green}" "${cl_normal}"
  362. read -rp "[?] Use swap file: (y/n) " _key
  363. if [ "${_key}" == "y" ]; then
  364. # Adding swap file
  365. printf "[-] Creating swap file 2Gb..."
  366. if dd if=/dev/zero of=/mnt/swapfile bs=2048 count=1000000; then
  367. printf "OK\n"
  368. else
  369. printf "[!] Error creating swap file\n"
  370. exit 1
  371. fi
  372. # Set up a Linux swap area
  373. mkswap -q /mnt/swapfile
  374. chmod 600 /mnt/swapfile
  375. printf "[+] Set up a swap file\n"
  376. # Adding swap file to /etc/fstab
  377. swap_uuid=$(swaplabel /mnt/swapfile | sed 's/:\s*/=/')
  378. printf "%s none swap sw 0 0\n" "${swap_uuid}" >> /mnt/etc/fstab
  379. printf "[+] Adding swap file to /etc/fstab\n"
  380. else
  381. printf "[+] Skipping swap file configure\n"
  382. fi
  383. printf "%s#######################%s\n" "${cl_blue}" "${cl_normal}"
  384. printf "%s# Finish install Void #%s\n" "${cl_blue}" "${cl_normal}"
  385. printf "%s#######################%s\n" "${cl_blue}" "${cl_normal}"
  386. printf "[?] Unmount newly created Void installation: (y/n) "
  387. read -r _key
  388. if [[ "${_key}" == "y" ]]; then
  389. umount -R /mnt # Unmount root volume
  390. vgchange -an "${lvm_name}" # Deactivate volume group
  391. cryptsetup close ${luks_name} # Close LUKS encrypted partition
  392. fi