You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

708 lines
15 KiB

  1. #!/bin/bash
  2. #
  3. set -e
  4. echo (){
  5. /bin/echo "#########################################"
  6. /bin/echo "$@"
  7. /bin/echo "#########################################"
  8. }
  9. #LICENSE#{{{
  10. # Copyright (c) 2012 Tom Wambold
  11. #
  12. # Permission is hereby granted, free of charge, to any person obtaining a copy
  13. # of this software and associated documentation files (the "Software"), to deal
  14. # in the Software without restriction, including without limitation the rights
  15. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. # copies of the Software, and to permit persons to whom the Software is
  17. # furnished to do so, subject to the following conditions:
  18. #
  19. # The above copyright notice and this permission notice shall be included in
  20. # all copies or substantial portions of the Software.
  21. #
  22. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. # SOFTWARE.
  29. #}}}
  30. # CONFIGURE THESE VARIABLES{{{
  31. # Drive to install to.
  32. DRIVE='/dev/sda'
  33. # Hostname of the installed machine.
  34. HOSTNAME='arch'
  35. # Encrypt everything (except /boot). true or false
  36. ENCRYPT_DRIVE=true
  37. # Passphrase used to encrypt the drive (leave blank to be prompted).
  38. DRIVE_PASSPHRASE=''
  39. # Root password (leave blank to be prompted).
  40. ROOT_PASSWORD=''
  41. # Main user to create (by default, added to wheel group, and others).
  42. USER_NAME='lelgenio'
  43. # Link to users dotfiles repo(git)
  44. # Assumed to have stow-able modules on its root(cd .dotfiles;stow*/)
  45. DOTFILES_URL="https://gitlab.com/$USER_NAME/dotfiles"
  46. USER_SHELL='fish'
  47. # The main user's password (leave blank to be prompted).
  48. USER_PASSWORD=''
  49. # System timezone.
  50. TIMEZONE='America/Sao_Paulo'
  51. # Country code for pacman repos
  52. COUNTRY='brazil'
  53. # Have /tmp on a tmpfs or not. Leave blank to disable.
  54. # Only leave this blank on systems with very little RAM.
  55. TMP_ON_TMPFS='TRUE'
  56. KEYMAP='br-abnt2'
  57. # KEYMAP='dvorak'
  58. LANG=pt_BR.UTF-8
  59. #}}}
  60. # Initial Setup{{{
  61. # Base install{{{
  62. setup() {
  63. local boot_dev="$DRIVE"1
  64. if "$ENCRYPT_DRIVE"
  65. then
  66. local crypt_dev="$DRIVE"2
  67. local lvm_dev="/dev/mapper/lvm"
  68. else
  69. local lvm_dev="$DRIVE"2
  70. fi
  71. echo 'Cleaning disk'
  72. disk_clean "$lvm_dev" "$DRIVE"2
  73. echo 'Creating partitions'
  74. partition_drive "$DRIVE"
  75. if "$ENCRYPT_DRIVE"
  76. then
  77. if [ -z "$DRIVE_PASSPHRASE" ];then
  78. echo 'Enter a passphrase to encrypt the disk:'
  79. read -s DRIVE_PASSPHRASE
  80. fi
  81. echo 'Encrypting partition'
  82. encrypt_drive "$crypt_dev" "$DRIVE_PASSPHRASE" lvm
  83. fi
  84. echo 'Setting up LVM'
  85. setup_lvm "$lvm_dev" vg00
  86. echo 'Formatting filesystems'
  87. format_filesystems "$boot_dev"
  88. echo 'Mounting filesystems'
  89. mount_filesystems "$boot_dev"
  90. echo 'Setting repos'
  91. set_repos
  92. echo 'Installing base system'
  93. install_base
  94. echo 'Setting fstab'
  95. set_fstab
  96. echo 'Chrooting into installed system to continue setup...'
  97. cp "$0" "/mnt/setup.sh"
  98. chmod +x "/mnt/setup.sh"
  99. arch-chroot /mnt "./setup.sh"
  100. if [ -f "/mnt/setup.sh" ];then
  101. echo 'ERROR: Something failed inside the chroot, not unmounting filesystems so you can investigate.'
  102. echo 'Make sure you unmount everything before you try to run this script again.'
  103. else
  104. echo 'Unmounting filesystems'
  105. unmount_filesystems
  106. echo 'Done! Reboot system.'
  107. fi
  108. }
  109. #}}}
  110. # Remove old LVMs{{{
  111. disk_clean(){
  112. local lvm_dev="$1"
  113. local disk="$2"
  114. echo 'cleaning disk'
  115. umount --recursive --quiet /mnt || true
  116. swapoff -a
  117. pvs "$lvm_dev" || return 0
  118. for vg in $(pvs -o vg_name --nohead "$lvm_dev")
  119. do
  120. vgremove "$vg" --yes
  121. done
  122. pvremove "$lvm_dev"
  123. if "$ENCRYPT_DRIVE"
  124. then
  125. cryptsetup close lvm
  126. fi
  127. wipefs -a "$disk"
  128. }
  129. #}}}
  130. # Partition Drive{{{
  131. partition_drive() {
  132. local dev="$1"; shift
  133. # 100 MB /boot partition, everything else under LVM
  134. if $IS_BIOS;then
  135. parted \
  136. --align optimal \
  137. --script "$dev" \
  138. mklabel msdos \
  139. mkpart primary fat32 1M 100M \
  140. mkpart primary ext4 100M 100% \
  141. set 1 boot on \
  142. set 2 lvm on
  143. else
  144. parted \
  145. --align optimal \
  146. --script "$dev" \
  147. mklabel gpt \
  148. mkpart boot 1 100M \
  149. mkpart lvm 100M 100% \
  150. set 1 boot on \
  151. set 2 lvm on
  152. fi
  153. }
  154. #}}}
  155. # Encrypt_drive {{{
  156. encrypt_drive() {
  157. local dev="$1"; shift
  158. local passphrase="$1"; shift
  159. local name="$1"; shift
  160. /bin/echo -en "$passphrase" | cryptsetup luksFormat "$dev"
  161. /bin/echo -en "$passphrase" | cryptsetup luksOpen "$dev" lvm
  162. }
  163. #}}}
  164. # setup_lvm{{{
  165. setup_lvm() {
  166. local partition="$1"; shift
  167. local volgroup="$1"; shift
  168. local d_size=$(lsblk --noheadings --nodeps --bytes --raw --output SIZE $DRIVE)
  169. local swap_size=$(free -b | awk '/^Mem/ { printf "%.0fG", 2*$2*10**-9}')
  170. pvcreate "$partition"
  171. vgcreate "$volgroup" "$partition"
  172. # Create a swap partition that is twice the amount of RAM
  173. lvcreate --yes -L$swap_size "$volgroup" -n swap
  174. # if the disk has more than 100Gb
  175. if [ "$d_size" -gt $( echo "100*10^9" | bc ) ]
  176. then
  177. # Create a 50GB root partition
  178. lvcreate --yes -L '50G' "$volgroup" -n root
  179. else
  180. # Create root partition on 50% of free space
  181. lvcreate --yes -l '+50%FREE' "$volgroup" -n root
  182. fi
  183. # Use the rest of the space for home
  184. lvcreate --yes -l '+100%FREE' "$volgroup" -n home
  185. # Enable the new volumes
  186. vgchange -ay
  187. }
  188. #}}}
  189. # format_filesystems #{{{
  190. format_filesystems() {
  191. local boot_dev="$1"; shift
  192. mkfs.fat "$boot_dev"
  193. mkfs.ext4 -L root /dev/vg00/root
  194. mkfs.ext4 -L home /dev/vg00/home
  195. mkswap /dev/vg00/swap
  196. }
  197. #}}}
  198. # mount_filesystems #{{{
  199. mount_filesystems() {
  200. local boot_dev="$1"; shift
  201. mount /dev/vg00/root /mnt
  202. mkdir /mnt/home
  203. mount /dev/vg00/home /mnt/home
  204. mkdir /mnt/boot
  205. mount "$boot_dev" /mnt/boot
  206. swapon /dev/vg00/swap
  207. }
  208. #}}}
  209. # set_repos() {{{{
  210. set_repos() {
  211. # /etc/pacman.conf{{{
  212. cat > /etc/pacman.conf <<EOF
  213. #
  214. # GENERAL OPTIONS
  215. #
  216. [options]
  217. HoldPkg = pacman glibc
  218. Architecture = auto
  219. # Misc options
  220. #UseSyslog
  221. Color
  222. ILoveCandy
  223. #TotalDownload
  224. CheckSpace
  225. #VerbosePkgLists
  226. SigLevel = Required DatabaseOptional
  227. LocalFileSigLevel = Optional
  228. #RemoteFileSigLevel = Required
  229. #
  230. # REPOSITORIES
  231. #
  232. #[testing]
  233. #Include = /etc/pacman.d/mirrorlist
  234. [core]
  235. Include = /etc/pacman.d/mirrorlist
  236. [extra]
  237. Include = /etc/pacman.d/mirrorlist
  238. #[community-testing]
  239. #Include = /etc/pacman.d/mirrorlist
  240. [community]
  241. Include = /etc/pacman.d/mirrorlist
  242. #[multilib-testing]
  243. #Include = /etc/pacman.d/mirrorlist
  244. [multilib]
  245. Include = /etc/pacman.d/mirrorlist
  246. EOF
  247. #}}}
  248. # /etc/pacman.d/mirrorlist{{{
  249. pacman -Sy reflector --noconfirm --needed
  250. reflector -c $COUNTRY -f 10 -p http -p https
  251. #}}}
  252. mkdir -p /mnt/etc/pacman.d
  253. cp -r /mnt/etc/pacman* /etc/
  254. }
  255. #}}}
  256. # install_base #{{{
  257. install_base() {
  258. pacstrap /mnt \
  259. base base-devel linux-zen linux-firmware intel-ucode grub \
  260. fish bluez cronie git man-db \
  261. iwd dhcpcd
  262. }
  263. #}}}
  264. # Set fstab {{{
  265. set_fstab() {
  266. genfstab -Up /mnt > /mnt/etc/fstab
  267. }
  268. #}}}
  269. # Unmount filesystems #{{{
  270. unmount_filesystems() {
  271. umount -R /mnt
  272. swapoff /dev/vg00/swap
  273. vgchange -an
  274. if $ENCRYPT_DRIVE
  275. then
  276. cryptsetup luksClose lvm
  277. fi
  278. }
  279. #}}}
  280. # is_bios{{{
  281. if ls /sys/firmware/efi/efivars/ &> /dev/null
  282. then
  283. IS_BIOS=false
  284. else
  285. IS_BIOS=true
  286. fi
  287. #}}}
  288. #}}}
  289. # Configuration{{{
  290. # configure() {#{{{
  291. configure() {
  292. local boot_dev="$DRIVE"1
  293. local lvm_dev="$DRIVE"2
  294. echo 'Setting hostname'
  295. set_hostname "$HOSTNAME"
  296. echo 'Setting timezone'
  297. set_timezone "$TIMEZONE"
  298. echo 'Setting locale'
  299. set_locale
  300. echo 'Setting console keymap'
  301. set_inputs
  302. echo 'Configuring initial ramdisk'
  303. set_initcpio
  304. echo 'Configuring Bluetooth'
  305. set_bluetooth
  306. echo 'Configuring bootloader'
  307. set_bootctl "$boot_dev" "$lvm_dev"
  308. echo 'Configuring sudo'
  309. set_sudoers
  310. echo 'Configuring PAM'
  311. set_pam
  312. echo 'Configuring logind'
  313. set_logind
  314. if [ -z "$ROOT_PASSWORD" ];then
  315. echo 'Enter the root password:'
  316. read -s ROOT_PASSWORD
  317. fi
  318. echo 'Setting root password'
  319. set_root_password "$ROOT_PASSWORD"
  320. if [ -z "$USER_PASSWORD" ];then
  321. echo "Enter the password for user $USER_NAME"
  322. read -s USER_PASSWORD
  323. fi
  324. echo 'Creating initial user'
  325. create_user "$USER_NAME" "$USER_PASSWORD"
  326. echo 'setting up user'
  327. cp $0 "/home/$USER_NAME/setup.sh"
  328. chown $USER_NAME "/home/$USER_NAME/setup.sh"
  329. su $USER_NAME -c "/home/$USER_NAME/setup.sh"
  330. shred "/home/$USER_NAME/setup.sh"
  331. rm "/home/$USER_NAME/setup.sh"
  332. echo 'Setting initial daemons'
  333. set_daemons "$TMP_ON_TMPFS"
  334. echo 'Updating pkgfile database'
  335. update_pkgfile
  336. }
  337. #}}}
  338. # set_hostname() {#{{{
  339. set_hostname() {
  340. local hostname="$1"; shift
  341. /bin/echo "$hostname" > /etc/hostname
  342. cat > /etc/hosts <<EOF
  343. 127.0.0.1 localhost.localdomain localhost $hostname
  344. ::1 localhost.localdomain localhost $hostname
  345. EOF
  346. }
  347. #}}}
  348. # set_timezone() {#{{{
  349. set_timezone() {
  350. local timezone="$1"; shift
  351. ln -sfT "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
  352. timedatectl set-ntp on
  353. hwclock --systohc || echo FAILED TO SET HW CLOCK
  354. }
  355. #}}}
  356. # set_locale() {#{{{
  357. set_locale() {
  358. cat > /etc/locale.conf <<EOF
  359. LANG=$LANG
  360. LC_COLLATE=C
  361. EOF
  362. cat > /etc/locale.gen <<EOF
  363. en_US.UTF-8 UTF-8
  364. $LANG UTF-8
  365. EOF
  366. locale-gen
  367. }
  368. #}}}
  369. # set_inputs() {#{{{
  370. set_inputs() {
  371. localectl set-keymap $KEYMAP
  372. mkdir -p /etc/X11/xorg.conf.d/
  373. cat > /etc/X11/xorg.conf.d/30-touchpad.conf <<EOF
  374. Section "InputClass"
  375. MatchIsTouchpad "on"
  376. Identifier "devname"
  377. Driver "libinput"
  378. Option "Tapping" "on"
  379. Option "ClickMethod" "clickfinger"
  380. Option "NaturalScrolling" "true"
  381. EndSection
  382. EOF
  383. }
  384. #}}}
  385. # set_initcpio() {#{{{
  386. set_initcpio() {
  387. local vid
  388. if [ "$VIDEO_DRIVER" = "i915" ];then
  389. vid='i915'
  390. elif [ "$VIDEO_DRIVER" = "nouveau" ];then
  391. vid='nouveau'
  392. elif [ "$VIDEO_DRIVER" = "radeon" ];then
  393. vid='radeon'
  394. fi
  395. local encrypt=""
  396. if $ENCRYPT_DRIVE
  397. then
  398. encrypt="encrypt keyboard"
  399. fi
  400. cat > /etc/mkinitcpio.conf <<EOF
  401. # vim:set ft=sh
  402. MODULES=(ext4 $vid)
  403. BINARIES=()
  404. FILES=()
  405. HOOKS=(base udev autodetect block $encrypt lvm2 filesystems fsck)
  406. EOF
  407. # Intall kernel, if necessary
  408. [ -f /boot/vmlinuz-linux-zen ] ||
  409. mkinitcpio -P
  410. }
  411. #}}}
  412. # set_daemons() {#{{{
  413. set_daemons() {
  414. local tmp_on_tmpfs="$1"; shift
  415. if [ -z "$tmp_on_tmpfs" ];then
  416. systemctl mask tmp.mount
  417. fi
  418. systemctl enable \
  419. cronie.service \
  420. iwd.service \
  421. dhcpcd.service \
  422. ly.service \
  423. # Ly{{{
  424. mkdir -p /etc/ly/
  425. cat > /etc/ly/config.ini << EOF
  426. animate = true
  427. blank_box = true
  428. hide_borders = true
  429. lang = br
  430. EOF
  431. #}}}
  432. }
  433. #}}}
  434. # set_bluetooth{{{
  435. set_bluetooth() {
  436. mkdir -p /etc/bluetooth/
  437. cat > /etc/bluetooth/main.conf <<EOF
  438. [General]
  439. DiscoverableTimeout = 0
  440. Discoverable = true
  441. AlwaysPairable = true
  442. [Policy]
  443. AutoEnable=true
  444. EOF
  445. }
  446. #}}}
  447. # set_boot_loader() {{{
  448. set_bootctl() {
  449. local boot_dev="$1"; shift
  450. local lvm_dev="$1"; shift
  451. local lvm_uuid=$(get_uuid "/dev/vg00/root")
  452. local k_args="root=UUID=$lvm_uuid"
  453. if $IS_BIOS;then
  454. cat >> /etc/default/grub <<EOF
  455. GRUB_CMDLINE_LINUX_DEFAULT="$k_args"
  456. # GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=3 vga=current rd.udev.log_priority=3 rd.systemd.show_status=auto vt.global_cursor_default=0 nmi_watchdog=0 $k_args"
  457. EOF
  458. grub-install "$DRIVE"
  459. grub-mkconfig -o /boot/grub/grub.cfg
  460. else
  461. bootctl install
  462. cat > /boot/loader/entries/arch.conf <<EOF
  463. title arch
  464. linux vmlinuz-linux-zen
  465. initrd intel-ucode.img
  466. initrd initramfs-linux-zen.img
  467. options $k_args
  468. # options quiet splash loglevel=3 vga=current rd.udev.log_priority=3 rd.systemd.show_status=auto vt.global_cursor_default=0 nmi_watchdog=0
  469. EOF
  470. fi
  471. }
  472. #}}}
  473. # set_sudoers() {#{{{
  474. set_sudoers() {
  475. cat > /etc/sudoers <<EOF
  476. ##
  477. ## User privilege specification
  478. ##
  479. root ALL=(ALL) ALL
  480. ## Uncomment to allow members of group wheel to execute any command
  481. # %wheel ALL=(ALL) ALL
  482. ## Same thing without a password
  483. %wheel ALL=(ALL) NOPASSWD: ALL
  484. ## Read drop-in files from /etc/sudoers.d
  485. ## (the '#' here does not indicate a comment)
  486. #includedir /etc/sudoers.d
  487. EOF
  488. chmod 440 /etc/sudoers
  489. }
  490. #}}}
  491. # set_pam{{{
  492. set_pam() {
  493. cat > /etc/pam.d/system-local-login <<EOF
  494. auth include system-login
  495. account include system-login
  496. password include system-login
  497. session include system-login
  498. auth optional pam_gnupg.so
  499. session optional pam_gnupg.so
  500. EOF
  501. }
  502. #}}}
  503. # set_logind{{{
  504. set_logind(){
  505. mkdir -p /etc/systemd
  506. cat > /etc/systemd/logind.conf <<EOF
  507. [Login]
  508. HandlePowerKey=suspend
  509. HandleSuspendKey=suspend
  510. HandleLidSwitch=ignore
  511. EOF
  512. }
  513. #}}}
  514. # set_root_password() {#{{{
  515. set_root_password() {
  516. local password="$1"; shift
  517. /bin/echo -en "$password\n$password" | passwd
  518. }
  519. #}}}
  520. # create_user() {#{{{
  521. create_user() {
  522. local name="$1"; shift
  523. local password="$1"; shift
  524. grep "^$name" /etc/passwd ||
  525. useradd -m -s /usr/bin/$USER_SHELL -G adm,systemd-journal,wheel,rfkill,games,network,video,audio,optical,floppy,storage,scanner,power,input "$name"
  526. /bin/echo -en "$password\n$password" | passwd "$name"
  527. }
  528. #}}}
  529. # update_pkgfile() {#{{{
  530. update_pkgfile() {
  531. pkgfile -u
  532. }
  533. #}}}
  534. # get_uuid() {#{{{
  535. get_uuid() {
  536. lsblk --noheadings --nodeps --output UUID "$1"
  537. }
  538. #}}}
  539. # is_chroot(){{{{
  540. is_chroot(){
  541. test "$(ls -id / | cut -d' ' -f1)" == "2"
  542. }
  543. #}}}
  544. #}}}
  545. # User setup{{{
  546. user_setup() {
  547. echo 'Installing packages'
  548. install_aur_packages
  549. echo 'Installing dotfiles'
  550. install_dots
  551. }
  552. # Install AUR helper #{{{
  553. install_aur_packages() {
  554. sudo pacman -S --needed git
  555. # getting yay
  556. if ! command -v yay
  557. then
  558. git clone http://aur.archlinux.org/yay.git ~/yay
  559. cd ~/yay
  560. makepkg -si --noconfirm
  561. cd -
  562. fi
  563. }
  564. #}}}
  565. # Install dotfiles{{{
  566. install_dots() {
  567. if [ ! -d ~/.dotfiles ];then
  568. git clone $DOTFILES_URL ~/.dotfiles
  569. fi
  570. if [ -f ~/.dotfiles/config.y*ml ]; then
  571. dotdrop --cfg ~/.dotfiles/config.y*ml install --force --no-banner
  572. fi
  573. }
  574. #}}}
  575. #}}}
  576. if [ ! "$USER" == "root" ];then
  577. user_setup
  578. elif is_chroot;then
  579. configure
  580. else
  581. setup
  582. fi
  583. # vim:foldmethod=marker