| 1 | # shellcheck shell=bash |
| 2 | # Desktop part: packages, dotfiles (stow), zsh, services. Sourced by install.sh; |
| 3 | # runs as the user, asks for sudo when it needs it. |
| 4 | |
| 5 | ################# |
| 6 | ## GATEKEEPING ## |
| 7 | ################# |
| 8 | |
| 9 | ## Prevent user from running this script as root |
| 10 | if [[ "$EUID" -eq 0 ]]; then |
| 11 | log ERROR "This script must NOT be run as root." |
| 12 | log INFO "If you need elevated privileges, the script will ask for sudo when required." |
| 13 | exit 1 |
| 14 | fi |
| 15 | |
| 16 | if [[ ! -f /etc/arch-release ]]; then |
| 17 | log ERROR "This is not Arch Linux. These dotfiles and this script are for Arch only." |
| 18 | exit 1 |
| 19 | fi |
| 20 | |
| 21 | ## Does this look like a system that is already set up? |
| 22 | ## (configs this repo doesn't provide, or another desktop's config) |
| 23 | check_fresh_system() { |
| 24 | local foreign=() desktops=() entry |
| 25 | for entry in "$HOME"/.config/*; do |
| 26 | [[ -e "$entry" ]] || continue |
| 27 | entry="$(basename "$entry")" |
| 28 | [[ -e "$currentDir/.config/$entry" ]] || foreign+=("$entry") |
| 29 | done |
| 30 | for entry in i3 sway niri river awesome bspwm openbox qtile xfce4 \ |
| 31 | kdeglobals plasma-org.kde.plasma.desktop-appletsrc gnome-session; do |
| 32 | [[ -e "$HOME/.config/$entry" ]] && desktops+=("$entry") |
| 33 | done |
| 34 | |
| 35 | ((${#foreign[@]} <= 10 && ${#desktops[@]} == 0)) && return 0 |
| 36 | |
| 37 | printf '\033[1;31m' |
| 38 | echo "==================================================================" |
| 39 | echo " This does NOT look like a fresh Arch install." |
| 40 | echo |
| 41 | ((${#desktops[@]})) && echo " Found another desktop's config: ${desktops[*]}" |
| 42 | ((${#foreign[@]} > 10)) && echo " Found ${#foreign[@]} entries in ~/.config that this repo doesn't provide." |
| 43 | echo |
| 44 | echo " This installer is meant for a freshly installed, unconfigured" |
| 45 | echo " system. On a system you already use it WILL change things you" |
| 46 | echo " care about: your configs get moved aside, your shell changes, and" |
| 47 | echo " lots of packages get installed." |
| 48 | echo "==================================================================" |
| 49 | printf '\033[0m' |
| 50 | local answer |
| 51 | read -rp "Type 'I understand' to continue anyway: " answer |
| 52 | [[ "$answer" == "I understand" ]] || { log WARN "Aborted."; exit 1; } |
| 53 | } |
| 54 | check_fresh_system |
| 55 | |
| 56 | |
| 57 | install_prerequisites() { |
| 58 | sudo pacman -S --needed --noconfirm stow gum git zsh |
| 59 | } |
| 60 | |
| 61 | ## Installs prerequisites |
| 62 | log INFO "Installing prerequisites: " |
| 63 | install_prerequisites |
| 64 | |
| 65 | |
| 66 | DISCLAIMER=$(gum style \ |
| 67 | --border double \ |
| 68 | --border-foreground 196 \ |
| 69 | --padding "1 2" \ |
| 70 | --bold \ |
| 71 | "⚠️ DISCLAIMER |
| 72 | |
| 73 | These are MY personal dotfiles, built for MY machine |
| 74 | (Lenovo Legion, Intel + NVIDIA hybrid, linux-zen) and the way I work. |
| 75 | They are NOT general purpose. They're public as a reference, |
| 76 | or for people who want exactly the same setup. |
| 77 | |
| 78 | Only run this on a FRESHLY INSTALLED, UNCONFIGURED Arch system. |
| 79 | |
| 80 | This script is provided AS IS, WITHOUT ANY WARRANTY. It will: |
| 81 | • Install a lot of packages (including NVIDIA drivers if selected) |
| 82 | • Move conflicting files in your \$HOME to ~/.aurora-backup/ |
| 83 | • Change your login shell to zsh |
| 84 | • Optionally write /etc/keyd and enable keyd |
| 85 | • Optionally write /etc/pam.d/{login,passwd} (GNOME keyring unlock) |
| 86 | • Enable the aurora-shell.service user unit |
| 87 | |
| 88 | Proceed at your OWN RISK." |
| 89 | ) |
| 90 | |
| 91 | confirm "$DISCLAIMER |
| 92 | |
| 93 | Do you understand the risks and want to continue?" || exit 1 |
| 94 | |
| 95 | |
| 96 | ####################### |
| 97 | ## Package selection ## |
| 98 | ####################### |
| 99 | SELECTED_PKGS=() |
| 100 | for list in utils dev gpu optional aur; do |
| 101 | case "$list" in |
| 102 | utils) prompt_style "Important utilities (Most likely go with defaults)" ;; |
| 103 | dev) prompt_style "Select Development Tools" ;; |
| 104 | gpu) prompt_style "Select GPU drivers" ;; |
| 105 | optional) prompt_style "Select Optional Desktop Packages" ;; |
| 106 | aur) prompt_style "Select AUR packages" ;; |
| 107 | esac |
| 108 | |
| 109 | if ((AUTO_YES)); then |
| 110 | mapfile -t picked < <(preselected "$list") |
| 111 | else |
| 112 | gum_to_array picked < <(choose_packages "$list") |
| 113 | fi |
| 114 | SELECTED_PKGS+=("${picked[@]}") |
| 115 | done |
| 116 | |
| 117 | |
| 118 | ########################## |
| 119 | ## Configure Everything ## |
| 120 | ########################## |
| 121 | WARNING=$(gum style \ |
| 122 | --border double \ |
| 123 | --border-foreground 196 \ |
| 124 | --padding "1 2" \ |
| 125 | --bold \ |
| 126 | "⚠️ Files in your \$HOME that conflict with this repo will be MOVED to |
| 127 | ~/.aurora-backup/<date>/ and replaced with symlinks from this repo.") |
| 128 | |
| 129 | if confirm "$WARNING |
| 130 | |
| 131 | Proceed with system configuration (stow, shell)?"; then |
| 132 | ################### |
| 133 | ## Stow dotfiles ## |
| 134 | ################### |
| 135 | log INFO "Detecting conflicts..." |
| 136 | mapfile -t conflicts < <(stow -t "$HOME" . --no-folding -nv 2>&1 | \ |
| 137 | sed -n 's/.*existing target \(.*\) since neither.*/\1/p') |
| 138 | |
| 139 | if ((${#conflicts[@]} == 0)); then |
| 140 | log INFO "No conflicts. Running stow normally..." |
| 141 | else |
| 142 | log WARN "These paths conflict and will be moved to a backup:" |
| 143 | printf ' %s\n' "${conflicts[@]}" |
| 144 | if ! confirm "Move these files to ~/.aurora-backup/ ?"; then |
| 145 | log WARN "Aborted." |
| 146 | exit 1 |
| 147 | fi |
| 148 | |
| 149 | # Move conflicts (relative to $HOME) into the backup dir, keeping their paths |
| 150 | BACKUP_DIR="$HOME/.aurora-backup/$(date '+%Y%m%d-%H%M%S')" |
| 151 | for path in "${conflicts[@]}"; do |
| 152 | [[ -n "$path" && "$path" != "/" ]] || continue |
| 153 | mkdir -p "$BACKUP_DIR/$(dirname "$path")" |
| 154 | mv "$HOME/$path" "$BACKUP_DIR/$path" && log INFO "Backed up $path" |
| 155 | done |
| 156 | log INFO "Backups are in $BACKUP_DIR" |
| 157 | fi |
| 158 | |
| 159 | stow -t "$HOME" . --no-folding \ |
| 160 | && log SUCCESS "Dotfiles stowed successfully" \ |
| 161 | || log ERROR "Stow failed" |
| 162 | |
| 163 | ################################# |
| 164 | ## Change default shell to zsh ## |
| 165 | ################################# |
| 166 | log INFO "Changing the default shell to ZSH" |
| 167 | if [[ "$SHELL" != "$(command -v zsh)" ]]; then |
| 168 | chsh -s "$(command -v zsh)" \ |
| 169 | && log SUCCESS "Default shell successfully set to zsh" \ |
| 170 | || log ERROR "Default shell could not be set to zsh" |
| 171 | else |
| 172 | log INFO "Skipping: zsh is already the default shell" |
| 173 | fi |
| 174 | else |
| 175 | log ERROR "Aborted stow, didn't configure or install anything" |
| 176 | exit 1 |
| 177 | fi |
| 178 | |
| 179 | |
| 180 | mapfile -t DESKTOP_PKGS < <(read_list desktop) |
| 181 | ALL_PKGS=( |
| 182 | "${DESKTOP_PKGS[@]}" |
| 183 | "${SELECTED_PKGS[@]}" |
| 184 | ) |
| 185 | |
| 186 | ######################## |
| 187 | ## Install Everything ## |
| 188 | ######################## |
| 189 | if ((${#ALL_PKGS[@]})); then |
| 190 | if confirm "Install all the selected packages?"; then |
| 191 | log INFO "Installing selected packages..." |
| 192 | |
| 193 | ## Installing paru if not installed already |
| 194 | if ! command -v paru >/dev/null 2>&1; then |
| 195 | log INFO "Installing Paru (AUR package manager)" |
| 196 | sudo pacman -S --needed --noconfirm base-devel |
| 197 | git clone https://aur.archlinux.org/paru.git |
| 198 | (cd paru && makepkg -sri) |
| 199 | rm -rf paru |
| 200 | fi |
| 201 | |
| 202 | if paru -Syu --needed "${ALL_PKGS[@]}"; then |
| 203 | INSTALL_STATUS="complete" |
| 204 | else |
| 205 | INSTALL_STATUS="failed" |
| 206 | fi |
| 207 | else |
| 208 | log WARN "Package installation skipped by user" |
| 209 | INSTALL_STATUS="partial" |
| 210 | fi |
| 211 | else |
| 212 | log WARN "No packages selected" |
| 213 | INSTALL_STATUS="partial" |
| 214 | fi |
| 215 | |
| 216 | |
| 217 | |
| 218 | ################ |
| 219 | ## Setup Keyd ## |
| 220 | ################ |
| 221 | if command -v keyd >/dev/null 2>&1; then |
| 222 | if confirm "Configure and enable keyd? "; then |
| 223 | log INFO "Copying keyd configuration to /etc/keyd/default.conf" |
| 224 | sudo cp "$currentDir/system/etc/keyd/default.conf" /etc/keyd/ |
| 225 | sudo systemctl enable --now keyd.service \ |
| 226 | && log SUCCESS "Successfully enabled keyd.service" \ |
| 227 | || log ERROR "Couldn't enable keyd.service" |
| 228 | fi |
| 229 | fi |
| 230 | |
| 231 | |
| 232 | ############################ |
| 233 | ## GNOME keyring on login ## |
| 234 | ############################ |
| 235 | # pam_gnome_keyring unlocks the "login" keyring with the login password (tty login and hyprlock, |
| 236 | # whose PAM file includes login); passwd keeps the keyring password in sync. |
| 237 | if confirm "Unlock GNOME keyring at login (writes /etc/pam.d/login and passwd)?"; then |
| 238 | log INFO "Copying PAM files to /etc/pam.d" |
| 239 | sudo cp "$currentDir/system/etc/pam.d/login" "$currentDir/system/etc/pam.d/passwd" /etc/pam.d/ \ |
| 240 | && log SUCCESS "GNOME keyring unlocks at login" \ |
| 241 | || log ERROR "Couldn't write /etc/pam.d" |
| 242 | fi |
| 243 | |
| 244 | |
| 245 | ######################### |
| 246 | ## Enable aurora shell ## |
| 247 | ######################### |
| 248 | # User unit, stowed to ~/.config/systemd/user. Hyprland starts it at login, |
| 249 | # enabling it also ties it to graphical-session.target. No --now: no session yet. |
| 250 | if [[ -f "$HOME/.config/systemd/user/aurora-shell.service" ]]; then |
| 251 | if confirm "Enable aurora-shell.service (the desktop shell)?"; then |
| 252 | systemctl --user daemon-reload |
| 253 | systemctl --user enable aurora-shell.service \ |
| 254 | && log SUCCESS "Successfully enabled aurora-shell.service" \ |
| 255 | || log ERROR "Couldn't enable aurora-shell.service (run 'systemctl --user enable aurora-shell' after logging in)" |
| 256 | fi |
| 257 | else |
| 258 | log WARN "aurora-shell.service is not stowed, skipping" |
| 259 | fi |
| 260 | |
| 261 | |
| 262 | #################### |
| 263 | ## Final dialogue ## |
| 264 | #################### |
| 265 | BACKUP_NOTE="" |
| 266 | [[ -n "$BACKUP_DIR" ]] && BACKUP_NOTE=" |
| 267 | |
| 268 | Your old conflicting files are in: |
| 269 | $BACKUP_DIR" |
| 270 | |
| 271 | case "$INSTALL_STATUS" in |
| 272 | complete) |
| 273 | gum style \ |
| 274 | --border rounded \ |
| 275 | --border-foreground 42 \ |
| 276 | --padding "1 2" \ |
| 277 | --bold \ |
| 278 | "✔ Installation Complete! |
| 279 | |
| 280 | All selected packages were installed successfully. |
| 281 | You may now reboot the system for all the changes to apply.$BACKUP_NOTE" |
| 282 | ;; |
| 283 | partial) |
| 284 | gum style \ |
| 285 | --border rounded \ |
| 286 | --border-foreground 220 \ |
| 287 | --padding "1 2" \ |
| 288 | --bold \ |
| 289 | "⚠ Setup Finished (Partial) |
| 290 | |
| 291 | Some steps were skipped by user choice. |
| 292 | Your system was NOT fully configured.$BACKUP_NOTE" |
| 293 | ;; |
| 294 | failed) |
| 295 | gum style \ |
| 296 | --border rounded \ |
| 297 | --border-foreground 196 \ |
| 298 | --padding "1 2" \ |
| 299 | --bold \ |
| 300 | "❌ Installation Failed |
| 301 | |
| 302 | One or more steps did not complete successfully. |
| 303 | Check the logs above.$BACKUP_NOTE" |
| 304 | ;; |
| 305 | *) |
| 306 | gum style --bold "Finished.$BACKUP_NOTE" |
| 307 | ;; |
| 308 | esac |