├── LICENSE ├── README.md └── simple-arch-installer /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Prabir Shrestha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simple-arch-installer 2 | 3 | ## Installing 4 | 5 | 1. Boot into the Arch Linux Live environment. 6 | 2. Use `iwctl station wlan0 connect "networkname"` to connect to the wifi. Internet connection is required for installation. 7 | 3. *[Optional]* If you would like to increase the terminal font size run `setfont solar24x32`. 8 | 4. Run the following command to start the installer. 9 | 10 | ```bash 11 | bash <(curl -sL https://bit.ly/simple-arch-installer) 12 | ``` 13 | 14 | ## License 15 | 16 | MIT 17 | -------------------------------------------------------------------------------- /simple-arch-installer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # To connect to wifi: 4 | # iwctl station wlan0 connect "networkname" 5 | # To install big font: 6 | # setfont solar24x32 7 | # To copy archlinux iso to device 8 | # dd if=archlinux.iso of=/dev/sdb bs=4M 9 | set -eo pipefail 10 | trap quit:no_message INT 11 | 12 | INSTALL_SCRIPT=install_os.sh 13 | EDITOR=vim 14 | 15 | select_disk() { 16 | lsblk -o name,model,serial,size 17 | select ENTRY in $(ls /dev/disk/by-id/ | grep -v '\-part*'); 18 | do 19 | DISK="/dev/disk/by-id/$ENTRY" 20 | break 21 | done 22 | } 23 | 24 | if [ -z "$DISK" ]; then 25 | select_disk 26 | fi 27 | 28 | grep MemTotal /proc/meminfo 29 | read -p "Enter swap size (ex: 0 or 8G): " SWAPSIZE 30 | read -p "Full disk wipe (y/n): " FULLDISKWIPE 31 | read -p "Enter hostname: " HOSTNAME 32 | read -p "Enter username: " USERNAME 33 | read -p "Enter dotfiles repository (ex: prabirshrestha/dotfiles): " DOTFILESREPO 34 | [ -d /sys/firmware/efi ] && IS_EFI=true || IS_EFI=false 35 | if cat /proc/cpuinfo | grep "model name" | grep -q "Intel"; then 36 | ISINTEL=true 37 | fi 38 | if cat /proc/cpuinfo | grep "model name" | grep -q "Amd"; then 39 | ISAMD=true 40 | fi 41 | 42 | write_script() { 43 | ( 44 | echo "#!/usr/bin/env bash" 45 | echo "#" 46 | echo "# Please review the install script below" 47 | echo "#" 48 | echo "set -euo pipefail" 49 | echo 50 | echo "export DISK=$DISK" 51 | echo "export BOOTDISK=\"\${DISK}-part1\"" 52 | echo "export ROOTDISK=\"\${DISK}-part2\"" 53 | echo "export SWAPSIZE=$SWAPSIZE" 54 | echo "export FULLDISKWIPE=$FULLDISKWIPE" 55 | echo "export IS_EFI=$IS_EFI" 56 | echo "export USERNAME=$USERNAME" 57 | echo "export HOSTNAME=$HOSTNAME" 58 | echo "export DOTFILESREPO=$DOTFILESREPO" 59 | echo "export ISINTEL=$ISINTEL" 60 | echo "export ISAMD=$ISAMD" 61 | echo 62 | echo "password1=x" 63 | echo "password2=y" 64 | echo "until [[ \$password1 == \$password2 ]]; do" 65 | echo " read -s -p \"Enter disk password: \" password1" 66 | echo " echo" 67 | echo " read -s -p \"Re-Enter disk password: \" password2" 68 | echo " echo" 69 | echo " DISKPASSWORD=\$password1" 70 | echo "done" 71 | echo "password1=x" 72 | echo "password2=y" 73 | echo "until [[ \$password1 == \$password2 ]]; do" 74 | echo " read -s -p \"Enter user password: \" password1" 75 | echo " echo" 76 | echo " read -s -p \"Re-Enter user password: \" password2" 77 | echo " echo" 78 | echo " USERPASSWORD=\$password1" 79 | echo "done" 80 | echo 81 | echo "#reflector --latest 20 --country 'United States' --protocol https --sort rate --save /etc/pacman.d/mirrorlist" 82 | echo 83 | echo "timedatectl set-ntp true" 84 | echo "curl -s https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init | bash -s -- -v" 85 | echo 86 | echo "[ \"\${FULLDISKWIPE}\" = \"y\" ] && pv --timer --rate --stop-at-size -s \"\$(blockdev --getsize64 \$DISK)\" /dev/zero > \$DISK" 87 | echo "sgdisk --zap-all \$DISK # zap anything existing" 88 | echo "sgdisk -o \$DISK # write a new GPT partition with protective MBR" 89 | echo 90 | echo "# Partition 1: 512M. EFI System Partition and Legacy BIOS boot with Legacy BOOT ON" 91 | echo "sgdisk -n 1:1M:+512M \$DISK # create partition 1 - first 512M" 92 | echo "sgdisk -t 1:EF00 \$DISK # Set partition type to ESP" 93 | echo "sgdisk -A 1:set:2 \$DISK # Turn legacy boot attribute on" 94 | echo "sgdisk -c:1:BOOT \$DISK # Set partition name to BOOT" 95 | echo 96 | echo "# Partition 2: 0:0. ZFS Linux System Partition" 97 | echo "sgdisk -n 2:0:0 \$DISK # Partition 2 - everything but the first 512M" 98 | echo "sgdisk -t 2:BE00 \$DISK # Set partition type to Linux" 99 | echo "sgdisk -c:2:ZROOT \$DISK # Set partition name to ZROOT" 100 | echo 101 | echo "[ ! -f /etc/hostid ] && zgenhostid # generate /etc/hostid" 102 | echo "sleep 1" 103 | echo "swapoff -a" 104 | echo 105 | echo "# create zfs pool" 106 | echo "if [[ \"\$DISKPASSWORD\" == \"\" ]]; then" 107 | echo " ZFSENCRYPTIONOPTIONS=" 108 | echo "else" 109 | echo " ZFSENCRYPTIONOPTIONS=\"-O encryption=aes-256-gcm -O keylocation=prompt -O keyformat=passphrase\"" 110 | echo "fi" 111 | echo "echo -n \"\$DISKPASSWORD\" | zpool create \$ZFSENCRYPTIONOPTIONS -o ashift=12 -o autotrim=on -O mountpoint=none -O relatime=on -O compression=lz4 -O acltype=posixacl -O xattr=sa zroot \$ROOTDISK" 112 | echo "zpool set cachefile=/etc/zfs/zpool.cache zroot" 113 | echo "zfs create -o mountpoint=none zroot/ROOT" 114 | echo "zfs create -o mountpoint=/ zroot/ROOT/default" 115 | echo "zfs create -o mountpoint=none zroot/data" 116 | echo "zfs create -o mountpoint=/home zroot/data/home" 117 | echo "zfs create -o mountpoint=/root zroot/data/home/root" 118 | echo "zfs create -o mountpoint=/home/\$USERNAME zroot/data/home/\$USERNAME" 119 | echo "zfs create -o mountpoint=/srv -o canmount=off zroot/srv" 120 | echo "zfs create -o mountpoint=/var -o canmount=off zroot/var" 121 | echo "zfs create -o mountpoint=/var/games -o canmount=on zroot/var/games" 122 | echo "zfs create -o mountpoint=/var/lib -o canmount=off zroot/var/lib" 123 | echo "zfs create -o mountpoint=/var/lib/docker -o canmount=on -o dedup=off zroot/var/lib/docker" 124 | echo "zfs create -o mountpoint=/var/lib/libvirt -o canmount=on zroot/var/lib/libvirt" 125 | echo "zfs create -o mountpoint=/var/log -o canmount=off zroot/var/log" 126 | echo "zfs create -o mountpoint=/var/cache -o canmount=off -o com.sun:auto-snapshot=false zroot/var/cache" 127 | echo "zfs create -o mountpoint=/var/spool -o canmount=off zroot/var/spool" 128 | echo "zfs create -o mountpoint=/var/www -o canmount=on zroot/var/www" 129 | echo "zfs create -o mountpoint=/usr -o canmount=off zroot/usr" 130 | echo "zfs create -o mountpoint=/usr/local -o canmount=off zroot/usr/local" 131 | echo "zpool set bootfs=zroot/ROOT/default zroot" 132 | echo "if [[ \"\$SWAPSIZE\" != \"0\" ]]; then" 133 | echo " zfs create -V \$SWAPSIZE -b \$(getconf PAGESIZE) -o logbias=throughput -o sync=always -o primarycache=metadata -o secondarycache=none -o com.sun:auto-snapshot=false -o compression=zle zroot/swap" 134 | echo " mkswap -f /dev/zvol/zroot/swap" 135 | echo " swapon /dev/zvol/zroot/swap" 136 | echo "fi" 137 | echo "swapoff -a" 138 | echo "zpool export zroot" 139 | echo "zpool import -R /mnt zroot" 140 | echo "[[ \"\$DISKPASSWORD\" != \"\" ]] && echo -n \"\$DISKPASSWORD\" | zfs load-key zroot" 141 | echo "zfs mount -la" 142 | echo 143 | echo "mkfs.fat -F32 \$BOOTDISK" 144 | echo "mkdir -p /mnt/boot/efi" 145 | echo "mount \$BOOTDISK /mnt/boot/efi" 146 | echo 147 | echo "pacstrap /mnt base base-devel linux-lts linux-firmware linux-lts-headers" 148 | echo "mkdir /mnt/etc/zfs" 149 | echo "cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache" 150 | echo "if [[ \"\$SWAPSIZE\" != \"0\" ]]; then" 151 | echo " echo \"/dev/zvol/zroot/swap none swap discard 0 0\" >> /mnt/etc/fstab" 152 | echo "fi" 153 | echo "cat << EOF >> /mnt/etc/fstab" 154 | echo "UUID=\"\$(blkid -s UUID -o value \$BOOTDISK)\" /boot/efi vfat defaults 0 0" 155 | echo "EOF" 156 | echo 157 | echo "arch-chroot /mnt sh <> /etc/pacman.conf" 166 | echo " echo 'Server = https://archzfs.com/\\\$repo/\\\$arch' >> /etc/pacman.conf" 167 | echo 168 | echo " pacman -Syu --noconfirm" 169 | echo " #pacman -S --noconfirm reflector" 170 | echo " #reflector --latest 20 --country 'United States' --protocol https --sort rate --save /etc/pacman.d/mirrorlist" 171 | echo " #pacman -S --noconfirm archzfs-linux-lts" 172 | echo " pacman -S --noconfirm archzfs-dkms linux-headers" 173 | echo " zpool set cachefile=/etc/zfs/zpool.cache zroot" 174 | echo " systemctl enable zfs.target zfs-import-cache zfs-mount zfs-import.target" 175 | echo 176 | echo " ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime" 177 | echo " hwclock --systohc" 178 | echo " systemctl enable systemd-timesyncd" 179 | echo " sed -i 's/#en_US.UTF/en_US.UTF/' /etc/locale.gen" 180 | echo " locale-gen" 181 | echo " echo \$HOSTNAME > /etc/hostname" 182 | echo " echo '127.0.0.1 localhost' > /etc/hosts" 183 | echo " echo '::1 localhost' >> /etc/hosts" 184 | echo " echo '127.0.0.1 \${HOSTNAME}.localdomain \${HOSTNAME}' >> /etc/hosts" 185 | echo 186 | echo " pacman -S --noconfirm efibootmgr" 187 | echo " mkdir -p /boot/efi/EFI/zbm" 188 | echo " curl -L https://github.com/zbm-dev/zfsbootmenu/releases/download/v1.12.0/zfsbootmenu-release-vmlinuz-x86_64-v1.12.0.EFI -o /boot/efi/EFI/zbm/zfsbootmenu.EFI" 189 | echo " efibootmgr --disk \$BOOTDISK --part 1 --create --label \"ZFSBootMenu\" --loader '\EFI\zbm\zfsbootmenu.EFI' --unicode \"spl_hostid=\$(hostid) zbm.timeout=2 zbm.prefer=zroot zbm.import_policy=hostid quiet\" --verbose" 190 | echo " zfs set org.zfsbootmenu:commandline=\"rw quiet\" zroot/ROOT" 191 | echo " zfs set org.zfsbootmenu:commandline=\"rw quiet\" zroot/ROOT/default" 192 | echo " zfs set canmount=noauto zroot/ROOT" 193 | echo " zfs set canmount=noauto zroot/ROOT/default" 194 | echo " if [ "\$ISINTEL" == \"true\" ]; then pacman -S --noconfirm intel-ucode xf86-video-intel libva-intel-driver; fi;" 195 | echo 196 | echo " chmod 700 /boot" 197 | echo " chmod 600 /boot/*" 198 | echo " chmod 700 /boot/efi" 199 | echo 200 | echo " sed -i 's/^MODULES=.*/MODULES=(i915 intel_agp)/' /etc/mkinitcpio.conf" 201 | echo " sed -i \"s|^HOOKS=.*|HOOKS=(base udev autodetect modconf keyboard block zfs filesystems)|g\" /etc/mkinitcpio.conf" 202 | echo " sed -i 's/^COMPRESSION=.*/COMPRESSION=(zstd)/' /etc/mkinitcpio.conf" 203 | echo " mkinitcpio -p linux-lts" 204 | echo 205 | echo " ### USER and SUDO configuration ###" 206 | echo " # bug: https://bugs.archlinux.org/task/79619" 207 | echo " pacman --noconfirm -U https://archive.archlinux.org/packages/s/systemd/systemd-254.3-1-x86_64.pkg.tar.zst" 208 | echo " pacman -S --noconfirm sudo" 209 | echo " sed -i '/%wheel ALL=(ALL:ALL) ALL/s/^#//' /etc/sudoers" 210 | echo " useradd --no-create-home --home /home/\$USERNAME -g users -G wheel \$USERNAME" 211 | echo " chown -R \$USERNAME /home/\$USERNAME" 212 | echo " passwd -d \"\$USERNAME\"" 213 | echo 214 | echo " ### AUR support via paru ###" 215 | echo " pacman -S --noconfirm git base-devel" 216 | echo " cd /tmp && curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/paru-bin.tar.gz && tar -xvf paru-bin.tar.gz && chmod 777 paru-bin && cd paru-bin" 217 | echo " su \"\$USERNAME\" -c \"makepkg -sirc --noconfirm && paru -S --noconfirm paru-bin\"" 218 | echo " cd /tmp && rm -rf /tmp/paru-bin" 219 | echo 220 | echo " ### NETWORK ###" 221 | echo " cat > /etc/systemd/network/20-wired.network <<\"END\"" 222 | echo "[Match]" 223 | echo "Name=en*" 224 | echo "Name=eth*" 225 | echo "" 226 | echo "[Network]" 227 | echo "DHCP=yes" 228 | echo "END" 229 | echo " #rm -f /etc/resolv.conf && systemctl enable systemd-resolved && ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf" 230 | echo " systemctl enable systemd-resolved" 231 | echo " systemctl enable systemd-networkd" 232 | echo 233 | echo " pacman -S --noconfirm iwd" 234 | echo " mkdir /etc/iwd" 235 | echo " cat > /etc/iwd/main.conf <<\"END\"" 236 | echo "[General]" 237 | echo "UseDefaultInterface=true" 238 | echo "EnableNetworkConfiguration=true" 239 | echo "END" 240 | echo "systemctl enable iwd" 241 | echo 242 | echo " ### FIREWALL ###" 243 | echo " pacman -S --noconfirm ufw" 244 | echo " ufw default allow outgoing" 245 | echo " ufw deny incoming" 246 | echo " systemctl enable ufw" 247 | echo 248 | echo " ### DOTFILEs ###" 249 | echo " pacman -S --noconfirm git" 250 | echo " su \"\$USERNAME\" -c \"paru -S --noconfirm dotter-rs-bin\"" 251 | echo " if [ \$DOTFILESREPO != \"\" ]; then su \$USERNAME -c 'git clone --recurse-submodules https://github.com/\$DOTFILESREPO.git ~/.dotfiles && cd ~/.dotfiles && dotter -vv && git remote rm origin && git remote add origin git@github.com:\$DOTFILESREPO.git'; fi;" 252 | echo 253 | echo " ### BLUETOOTH ###" 254 | echo " pacman -S --noconfirm bluez bluez-utils blueman; systemctl enable bluetooth.service" 255 | echo 256 | echo " ### SOUND ###" 257 | echo " pacman -S --noconfirm pipewire pipewire-alsa pipewire-pulse pipewire-media-session pavucontrol" 258 | echo " su \"\$USERNAME\" -c \"systemctl --user enable pipewire.service pipewire.socket pipewire-media-session.service pipewire-pulse.service pipewire-pulse.socket\"" 259 | echo 260 | echo " ### GUI ###" 261 | echo " pacman -S --noconfirm xorg-drivers" 262 | echo " pacman -S --noconfirm sddm; systemctl enable sddm.service" 263 | echo " pacman -S --noconfirm noto-fonts noto-fonts-extra noto-fonts-cjk noto-fonts-emoji" 264 | echo " pacman -S --noconfirm bspwm sxhkd polybar picom rofi" 265 | echo " #pacman -S --noconfirm awesome nemo gvfs-smb rofi arc-icon-theme xsel" 266 | echo " #pacman -S --noconfirm xorg xfce4 xfce4-goodies" 267 | echo " #pacman -S --noconfirm gnome gdm gnome-tweak-tool; systemctl enable gdm" 268 | echo " #pacman -S --noconfirm plasma konsole" 269 | echo 270 | echo " su \"\$USERNAME\" -c \"paru -S --noconfirm google-chrome\"" 271 | echo " #pacman -S --noconfirm chromium" 272 | echo 273 | echo " ### DEV ###" 274 | echo " pacman -S --noconfirm age sops bore lua gvim git openssh tmux zip unzip wget ripgrep fzf man flameshot libz3 github-cli tree zoxide wezterm xterm lsof net-tools rustscan just" 275 | echo " pacman -S --noconfirm remmina freerdp" 276 | echo " pacman -S --noconfirm rustup cargo-edit cargo-watch && rustup install stable && rustup component add rust-src" 277 | echo " #pacman -S --noconfirm rust rust-src rust-analyzer cargo-edit cargo-outdated cargo-watch" 278 | echo 279 | echo " pacman -S --noconfirm tailscale" 280 | echo " systemctl enable --now tailscaled # run 'tailscale up' to authenticate after restart" 281 | echo " paru -S --noconfirm tailscale-systray-git" 282 | echo 283 | echo " mkdir -p /etc/docker" 284 | echo " echo '{\"storage-driver\":\"zfs\"}' >> /etc/docker/daemon.json" 285 | echo " pacman -S --noconfirm docker; systemctl enable docker" 286 | echo 287 | echo " su \$USERNAME -c 'paru -S --noconfirm zrepl-bin'" 288 | echo " mkdir -p /etc/zrepl" 289 | echo " cat > /etc/zrepl/zrepl.yml <<\"END\"" 290 | echo "jobs:" 291 | echo "- name: snapjob" 292 | echo " type: snap" 293 | echo " filesystems: {" 294 | echo " \"zroot<\": true," 295 | echo " \"zroot/data/var/tmp\": false," 296 | echo " \"zroot/data/var/cache\": false," 297 | echo " \"zroot/tmp\": false," 298 | echo " }" 299 | echo " snapshotting:" 300 | echo " type: periodic" 301 | echo " interval: 15m" 302 | echo " prefix: zrepl_" 303 | echo " pruning:" 304 | echo " keep:" 305 | echo " # fade-out scheme for snapshots starting with zrepl_" 306 | echo " - type: grid" 307 | echo " grid: 1x1h(keep=all) | 24x1h | 30x1d | 6x30d" 308 | echo " regex: \"^zrepl_.*\"" 309 | echo " # keep all snapshots that don't have the zrepl_ prefix" 310 | echo " - type: regex" 311 | echo " negate: true" 312 | echo " regex: \"^zrepl_.*\"" 313 | echo "END" 314 | echo " systemctl enable zrepl" 315 | echo 316 | echo " echo \"\$USERNAME:\$USERPASSWORD\" | chpasswd" 317 | echo " passwd -l root" 318 | echo " zfs snapshot -r zroot@install" 319 | echo "EOF" 320 | echo 321 | echo "umount /mnt/boot/efi" 322 | echo "zfs umount -a" 323 | echo "zpool export zroot" 324 | echo 325 | echo "echo \"OS setup complete. Please 'reboot' your machine.\"" 326 | ) > "$INSTALL_SCRIPT" 327 | chmod +x "$INSTALL_SCRIPT" 328 | } 329 | 330 | write_script 331 | 332 | # open editor to review and make last changes to the script 333 | "$EDITOR" "$INSTALL_SCRIPT" 334 | reset 335 | 336 | clear 337 | 338 | read -p "Are you sure you want to run the OS installer script (YES is capital letter to run): " RUN_INSTALLER 339 | if [ "$RUN_INSTALLER" == "YES" ]; then 340 | bash "$INSTALL_SCRIPT" 341 | else 342 | echo "Cancelling installation" 343 | fi 344 | --------------------------------------------------------------------------------