aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-04-21 01:23:38 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-04-21 01:23:38 +0100
commit31345ce0db8112308b78d7f09b9f1dd2c3973b73 (patch)
tree84a72484ad43350f1a80130de8b582b3e412c9a8
parent91b093c4b278fe37f316deef66cee1ee90892eba (diff)
downloaddotfiles-31345ce0db8112308b78d7f09b9f1dd2c3973b73.tar.gz
dotfiles-31345ce0db8112308b78d7f09b9f1dd2c3973b73.tar.bz2
dotfiles-31345ce0db8112308b78d7f09b9f1dd2c3973b73.zip
feat: add bootstrap.sh for fresh Arch installs
Takes a minimal Arch system (only 'base' installed) to the point where 'just init' has run and dotfiles are deployed. Installs prerequisites (sudo, git, base-devel, chezmoi, just, efibootmgr), enables %wheel in sudoers, bootstraps paru-bin from the AUR, clones the repo, runs 'just init' (which swaps sudo for doas-sudo-shim via the existing base meta list), and launches create-efi if no Arch EFI boot entry exists. Designed to be curlable: curl -fsSL https://raw.githubusercontent.com/sommerfelddev/dotfiles/master/bootstrap.sh | sh
-rw-r--r--.github/copilot-instructions.md1
-rw-r--r--README.md16
-rwxr-xr-xbootstrap.sh80
3 files changed, 96 insertions, 1 deletions
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 219ac1b..2a837f5 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -17,6 +17,7 @@ The repo root is a chezmoi source directory. Files targeting `$HOME` use chezmoi
- `meta/` contains plain text package lists for Arch Linux (one package per line, `#` comments). Each `.txt` file represents a group (e.g. `base.txt`, `dev.txt`, `wayland.txt`). Install with `just install base dev` or `just install-all`. Detect drift with `just status`.
- `firefox/` contains Firefox/LibreWolf hardening overrides (`user-overrides.js`) and custom CSS (`chrome/userChrome.css`). Deployed by `run_onchange_after_deploy-firefox.sh.tmpl`.
- `dot_local/bin/executable_create-efi` is an interactive EFI boot entry creation script using `efibootmgr` (deployed to `~/.local/bin/create-efi`).
+- `bootstrap.sh` at the repo root is a POSIX shell script that takes a fresh minimal Arch install (only `base`) to a fully deployed state. It installs prerequisites, enables `%wheel` sudoers, bootstraps `paru-bin` from the AUR, clones the repo, runs `just init`, and optionally invokes `create-efi`. Designed to be curlable: `curl -fsSL .../bootstrap.sh | sh`.
- `.chezmoiignore` excludes non-home files (`etc/`, `meta/`, `firefox/`, docs) from deployment to `$HOME`.
- `.githooks/` contains git hooks (notably `post-commit` which runs `chezmoi apply`). Activated by `just init`.
- `justfile` provides recipes: `init` (first-time setup), `sync` (apply + fix), `apply`, `fix`, `status`, `pkg-drift`, `dotfile-drift`, `undeclared`, `diff`, `merge`, `groups`, `install`, `install-all`, `add`, `remove`. Run `just` or `just --list` to see them.
diff --git a/README.md b/README.md
index c434b03..af8264c 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,21 @@
My Arch Linux configuration, managed with [chezmoi](https://www.chezmoi.io/).
-## Setup
+## Bootstrap on a fresh Arch install
+
+On a minimal Arch system (only `base` installed), as the regular wheel
+user:
+
+```sh
+curl -fsSL https://raw.githubusercontent.com/sommerfelddev/dotfiles/master/bootstrap.sh | sh
+```
+
+This installs prerequisites, enables `%wheel` in sudoers, builds
+`paru-bin` from the AUR, clones this repo to `~/dotfiles`, runs
+`just init`, and — on EFI systems missing an Arch boot entry —
+launches `create-efi`.
+
+## Setup on an existing system
```sh
chezmoi init --source ~/dotfiles
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..09983f3
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+# bootstrap.sh — take a fresh minimal Arch install (only the 'base'
+# meta-package installed) to the point where `just init` has run and
+# the dotfiles are deployed.
+#
+# Must be executed as the regular (non-root) user that will own the
+# system. paru and makepkg refuse to run as root, so we keep everything
+# user-side and only escalate for the pacman + sudoers step.
+#
+# Usage:
+# curl -fsSL https://raw.githubusercontent.com/sommerfelddev/dotfiles/master/bootstrap.sh | sh
+#
+# Overrides:
+# DOTFILES_REPO (default: https://github.com/sommerfelddev/dotfiles.git)
+# DOTFILES_DIR (default: $HOME/dotfiles)
+
+set -eu
+
+log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
+die() { printf '\033[1;31m==>\033[0m %s\n' "$*" >&2; exit 1; }
+
+# 0. refuse root — paru/makepkg won't run as root
+[ "$(id -u)" -ne 0 ] || die "run this as your regular user, not root"
+
+# 1. user must be in wheel (required so the sudoers rule we enable takes effect)
+id -nG "$USER" | tr ' ' '\n' | grep -qx wheel \
+ || die "user '$USER' must be in the 'wheel' group"
+
+# 2. install sudo + pacman prerequisites, enable wheel in sudoers.
+# If sudo is absent we do this in a single su -c so the root password
+# is entered only once. If sudo is already there, reuse it.
+PREREQS='sudo git base-devel chezmoi just efibootmgr'
+SUDOERS_SED='s/^# *\(%wheel ALL=(ALL:ALL\(:ALL\)*) ALL\)/\1/'
+
+if ! command -v sudo >/dev/null 2>&1; then
+ log 'installing prerequisites (prompting for root password)'
+ su -c "pacman -Syu --needed --noconfirm ${PREREQS} && \
+ sed -i '${SUDOERS_SED}' /etc/sudoers"
+else
+ log 'installing prerequisites'
+ # shellcheck disable=SC2086 # PREREQS is an intentional word list
+ sudo pacman -Syu --needed --noconfirm ${PREREQS}
+ sudo sed -i "${SUDOERS_SED}" /etc/sudoers
+fi
+
+# 3. bootstrap paru-bin from AUR if missing
+if ! command -v paru >/dev/null 2>&1; then
+ log 'building paru-bin from AUR'
+ tmp=$(mktemp -d)
+ trap 'rm -rf "$tmp"' EXIT
+ git clone --depth=1 https://aur.archlinux.org/paru-bin.git "$tmp/paru-bin"
+ (cd "$tmp/paru-bin" && makepkg -si --noconfirm)
+fi
+
+# 4. clone dotfiles
+DOTFILES_DIR="${DOTFILES_DIR:-$HOME/dotfiles}"
+REPO_URL="${DOTFILES_REPO:-https://github.com/sommerfelddev/dotfiles.git}"
+if [ ! -d "$DOTFILES_DIR/.git" ]; then
+ log "cloning $REPO_URL -> $DOTFILES_DIR"
+ git clone "$REPO_URL" "$DOTFILES_DIR"
+else
+ log "using existing clone at $DOTFILES_DIR"
+fi
+
+# 5. run just init — this deploys chezmoi, installs the 'base' meta list
+# (swapping sudo for doas-sudo-shim via paru -S --ask=4), deploys
+# /etc/doas.conf, and installs git hooks.
+cd "$DOTFILES_DIR"
+log 'running just init'
+just init
+
+# 6. optional: create an Arch EFI boot entry if none exists
+if [ -d /sys/firmware/efi ]; then
+ if ! sudo efibootmgr 2>/dev/null | grep -iq arch; then
+ log 'no Arch Linux EFI boot entry found; launching create-efi'
+ "$HOME/.local/bin/create-efi"
+ fi
+fi
+
+log 'done. Log out and back in (or reboot) to pick up shell and group changes.'