Files
dotfiles/bootstrap.sh
thomas 19d6936aa6 Feature: Enable hypridle without locking during Sunshine streams
Sunshine's global_prep_cmd now runs hypr/scripts/SunshineIdle.sh, which
holds a systemd idle inhibitor for the length of a stream (hypridle
respects it) and unlocks hyprlock if the session was already locked.
With that in place hypridle starts at login again.

Sunshine's config (sunshine.conf, apps.json, prep scripts) moves into
the dotfiles; credentials, logs and state stay local and are gitignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:14:44 +01:00

169 lines
5.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Sets up a fresh Arch install: drivers, packages, dotfiles and system config.
# Safe to re-run; anything already installed is skipped.
#
# Usage: ./bootstrap.sh [--svt-av1 | --no-svt-av1]
# --svt-av1 also install svt-av1-essential-git and rebuild ffmpeg against it
# --no-svt-av1 skip that without asking
# (neither) ask
set -euo pipefail
repo="$(cd "$(dirname "$0")" && pwd)"
list="$repo/system/packages.txt"
svt_av1=ask
for arg in "$@"; do
case "$arg" in
--svt-av1) svt_av1=yes ;;
--no-svt-av1) svt_av1=no ;;
*) echo "Unknown option: $arg" >&2; exit 1 ;;
esac
done
if (( EUID == 0 )); then
echo "Run this as your normal user, not root (it uses sudo where needed)." >&2
exit 1
fi
step() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; }
# Prints the packages under a [section] of packages.txt, skipping comments
packages() {
awk -v want="[$1]" '
/^\[/ { section = $1; next }
section == want { sub(/#.*/, ""); if (NF) print $1 }
' "$list"
}
# --- System config -----------------------------------------------------------
step "System config (pacman options)"
"$repo/system/install.sh"
step "Enabling multilib (needed for Steam and 32-bit drivers)"
if ! grep -q '^\[multilib\]' /etc/pacman.conf; then
sudo sed -i '/^#\[multilib\]/,/^#Include/ s/^#//' /etc/pacman.conf
fi
sudo pacman -Syu --needed --noconfirm pciutils git base-devel
# --- Hardware ----------------------------------------------------------------
step "Detecting CPU and GPU"
hw=()
case "$(grep -m1 '^vendor_id' /proc/cpuinfo | awk '{print $3}')" in
AuthenticAMD) hw+=(amd-ucode); echo "CPU: AMD" ;;
GenuineIntel) hw+=(intel-ucode); echo "CPU: Intel" ;;
*) echo "CPU: unknown vendor, skipping microcode" ;;
esac
# Vendor column of every display controller, e.g. "NVIDIA Corporation"
gpus="$(lspci -mm | awk -F'"' '$2 ~ /VGA|3D|Display/ { print $4 }')"
if grep -q NVIDIA <<<"$gpus"; then
echo "GPU: NVIDIA"
# nvidia-open only ships modules for the stock `linux` kernel; any other
# kernel needs the DKMS build. Supports Turing (GTX 16xx / RTX 20xx) and newer.
if pacman -Qq linux-lts linux-zen linux-hardened >/dev/null 2>&1; then
hw+=(nvidia-open-dkms linux-headers)
else
hw+=(nvidia-open)
fi
hw+=(nvidia-utils lib32-nvidia-utils libva-nvidia-driver)
fi
if grep -q 'Advanced Micro Devices' <<<"$gpus"; then
echo "GPU: AMD"
hw+=(mesa lib32-mesa vulkan-radeon lib32-vulkan-radeon)
fi
if grep -q 'Intel Corporation' <<<"$gpus"; then
echo "GPU: Intel"
hw+=(mesa lib32-mesa vulkan-intel lib32-vulkan-intel intel-media-driver)
fi
# Installed before the main list so Steam's 32-bit Vulkan dependency is
# already satisfied by the right driver
if (( ${#hw[@]} )); then
sudo pacman -S --needed --noconfirm "${hw[@]}"
fi
# --- Packages ----------------------------------------------------------------
step "Official repo packages"
mapfile -t pkgs < <(packages pacman)
sudo pacman -S --needed --noconfirm "${pkgs[@]}"
step "yay (AUR helper)"
if ! command -v yay >/dev/null; then
build="$(mktemp -d)"
git clone https://aur.archlinux.org/yay-bin.git "$build/yay-bin"
(cd "$build/yay-bin" && makepkg -si --noconfirm)
rm -rf "$build"
else
echo "already installed"
fi
step "AUR packages"
mapfile -t pkgs < <(packages aur)
yay -S --needed --noconfirm "${pkgs[@]}"
step "Flatpak apps"
sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
mapfile -t pkgs < <(packages flatpak)
sudo flatpak install -y --noninteractive flathub "${pkgs[@]}"
step "Apps from official install scripts"
mkdir -p "$HOME/.local/bin"
for app in $(packages installer); do
if command -v "$app" >/dev/null || [[ -x "$HOME/.local/bin/$app" ]]; then
echo "$app: already installed"
continue
fi
case "$app" in
claude) curl -fsSL https://claude.ai/install.sh | bash ;;
oh-my-posh) curl -fsSL https://ohmyposh.dev/install.sh | bash -s -- -d "$HOME/.local/bin" ;;
*) echo "$app: no install recipe in bootstrap.sh, skipping" >&2 ;;
esac
done
# --- Optional: SVT-AV1 essential + ffmpeg rebuild ----------------------------
if [[ $svt_av1 == ask ]]; then
read -rp $'\nInstall svt-av1-essential-git and rebuild ffmpeg against it? (slow) [y/N] ' reply
[[ $reply == [yY]* ]] && svt_av1=yes || svt_av1=no
fi
if [[ $svt_av1 == yes ]]; then
step "svt-av1-essential-git"
# Interactive on purpose: pacman asks to replace the conflicting svt-av1,
# and --noconfirm would answer no
yay -S --needed svt-av1-essential-git
step "Rebuilding ffmpeg against svt-av1-essential-git"
"$repo/system/rebuild-ffmpeg.sh"
fi
# --- Services ----------------------------------------------------------------
step "Enabling services"
# Not started now: sddm would take over the screen mid-script. They come up on reboot.
mapfile -t units < <(packages services)
sudo systemctl enable "${units[@]}"
# --- Dotfiles ----------------------------------------------------------------
step "Linking dotfiles with stow"
# Create real parent dirs first, otherwise stow symlinks the whole directory
# (e.g. ~/.config) into the repo and every app's files end up in git
mkdir -p "$HOME/.config" "$HOME/.local/bin" "$HOME/.local/share" "$HOME/Pictures"
# Sunshine keeps credentials and logs beside its config; those must stay out of git
mkdir -p "$HOME/.config/sunshine"
mkdir -p -m 700 "$HOME/.ssh"
if ! stow -d "$repo" -t "$HOME" --restow dotfiles; then
echo "stow hit conflicts (listed above). Move those files aside, then run:" >&2
echo " stow -d \"$repo\" -t \"\$HOME\" dotfiles" >&2
fi
if [[ "$(getent passwd "$USER" | cut -d: -f7)" != */zsh ]]; then
step "Setting zsh as login shell"
chsh -s /usr/bin/zsh
fi
step "Done — reboot to load drivers and start Hyprland"