modules: preflight + core packages (arch pacman + apt, yay, gh-release fallback)
This commit is contained in:
parent
8057fbac4d
commit
a9ba810bbc
38
modules/00-preflight.sh
Executable file
38
modules/00-preflight.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# 00-preflight — verify we can proceed at all.
|
||||
|
||||
step_name="preflight"
|
||||
step_desc="verify distro, network, privileges"
|
||||
step_run="run_preflight"
|
||||
|
||||
run_preflight() {
|
||||
log "preflight checks"
|
||||
|
||||
if [[ "$DISTRO" == "unknown" ]]; then
|
||||
err "unsupported distro (could not read ID/ID_LIKE from /etc/os-release)"
|
||||
err "bootstrap supports debian/ubuntu and arch only."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( EUID == 0 )); then
|
||||
SUDO=""
|
||||
export SUDO
|
||||
else
|
||||
SUDO="sudo"
|
||||
export SUDO
|
||||
if ! sudo -n true 2>/dev/null; then
|
||||
warn "not root and passwordless sudo unavailable — sudo will prompt per-use"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v ping >/dev/null 2>&1 && ping -c1 -W2 8.8.8.8 >/dev/null 2>&1; then
|
||||
:
|
||||
elif curl -fsS --max-time 3 https://g.mk.fo >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
err "no outbound network — cannot install anything"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ok "distro=$DISTRO arch=$ARCH user=$USER sudo=${SUDO:-root}"
|
||||
}
|
||||
152
modules/10-packages.sh
Executable file
152
modules/10-packages.sh
Executable file
@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env bash
|
||||
# 10-packages — core CLI utilities, per distro.
|
||||
|
||||
step_name="packages"
|
||||
step_desc="git byobu ufw mosh btop eza fzf ripgrep bat zoxide jq fd ..."
|
||||
step_run="run_packages"
|
||||
|
||||
# Tools we want everywhere (names canonical, mapped per-distro).
|
||||
PKGS_COMMON=(
|
||||
git byobu ufw mosh btop fzf ripgrep fd bat dust procs jq yq tree ncdu duf
|
||||
tldr httpie rsync lazygit neovim curl unzip less starship eza zoxide openssh
|
||||
)
|
||||
|
||||
run_packages() {
|
||||
log "installing core packages ($DISTRO)"
|
||||
case "$DISTRO" in
|
||||
arch) _pkg_arch ;;
|
||||
debian) _pkg_debian ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── arch ─────────────────────────────────────────────────────────────────────
|
||||
_pkg_arch() {
|
||||
sudo_ pacman -Sy --noconfirm --needed base-devel openssh
|
||||
# most tools live in extra/community (the merged repos); names map 1:1
|
||||
local p=(git byobu ufw mosh btop fzf ripgrep fd bat dust procs jq yq tree
|
||||
ncdu duf tldr httpie rsync lazygit neovim curl unzip less starship
|
||||
eza zoxide openssh)
|
||||
sudo_ pacman -Sy --noconfirm --needed "${p[@]}"
|
||||
_install_yay
|
||||
|
||||
# fd/bat ship with their real names on arch — no shims needed
|
||||
}
|
||||
|
||||
_install_yay() {
|
||||
if command -v yay >/dev/null 2>&1; then ok "yay already installed"; return; fi
|
||||
log "building yay from AUR (requires a non-root sudoer)"
|
||||
if (( EUID == 0 )) && [[ -z "${SUDO_USER:-}" ]]; then
|
||||
err "running as root with no SUDO_USER — yay cannot build. Re-run bootstrap as a normal user with sudo."
|
||||
return 1
|
||||
fi
|
||||
local tmp; tmp="$(mktemp -d)"
|
||||
as_user git clone --depth 1 https://aur.archlinux.org/yay.git "$tmp/yay"
|
||||
( cd "$tmp/yay" && as_user makepkg -si --noconfirm )
|
||||
rm -rf "$tmp"
|
||||
command -v yay >/dev/null 2>&1 && ok "yay installed" || warn "yay install may need a manual pass"
|
||||
}
|
||||
|
||||
# ── debian/ubuntu ────────────────────────────────────────────────────────────
|
||||
_pkg_debian() {
|
||||
sudo_ apt-get update -y
|
||||
sudo_ apt-get install -y ca-certificates curl gnupg lsb-release unzip less \
|
||||
git byobu ufw mosh btop fzf ripgrep jq tree ncdu rsync neovim curl \
|
||||
openssh-server sudo
|
||||
|
||||
# rename packages: fd -> fdfind, bat -> batcat (fix via aliases in zsh)
|
||||
sudo_ apt-get install -y fdfind batcat 2>/dev/null || true
|
||||
|
||||
# eza via the gierens PPA (debs not in base apt)
|
||||
if ! command -v eza >/dev/null 2>&1; then
|
||||
sudo_ install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://raw.githubusercontent.com/eza-community/eza/main/deb.asc \
|
||||
| sudo_ tee /etc/apt/keyrings/gierens.gpg >/dev/null
|
||||
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://apt.fury.io/eza/ /" \
|
||||
| sudo_ tee /etc/apt/sources.list.d/eza.list >/dev/null
|
||||
sudo_ apt-get update -y && sudo_ apt-get install -y eza || warn "eza PPA failed"
|
||||
fi
|
||||
|
||||
# starship: official installer
|
||||
if ! command -v starship >/dev/null 2>&1; then
|
||||
curl -sS https://starship.rs/install.sh | sh -s -- -y || warn "starship install failed"
|
||||
fi
|
||||
|
||||
# zoxide: official installer
|
||||
if ! command -v zoxide >/dev/null 2>&1; then
|
||||
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash || warn "zoxide install failed"
|
||||
fi
|
||||
|
||||
# yq: direct binary from mikefarah/yq releases (stable URL)
|
||||
if ! command -v yq >/dev/null 2>&1; then
|
||||
local suffix="amd64"; [[ "$ARCH" == "arm64" ]] && suffix="arm64"
|
||||
sudo_ wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${suffix}" \
|
||||
&& sudo_ chmod +x /usr/local/bin/yq || warn "yq install failed"
|
||||
fi
|
||||
|
||||
# tldr on debian: python3 package if present, else skip (npm-based out of scope here)
|
||||
if ! command -v tldr >/dev/null 2>&1; then
|
||||
sudo_ apt-get install -y tldr 2>/dev/null || warn "tldr not packaged on this release — skipped (install via npm later)"
|
||||
fi
|
||||
|
||||
# rest via GitHub release tarballs where missing (best-effort, arch auto-detected)
|
||||
_gh_release_binary bootandy/dust dust
|
||||
_gh_release_binary muesli/duf duf
|
||||
_gh_release_binary dalance/procs procs
|
||||
_gh_release_binary jesseduffield/lazygit lazygit
|
||||
# fd/bat on debian come from apt as fdfind/batcat (shimmed below)
|
||||
|
||||
_apt_aliases_fixup
|
||||
}
|
||||
|
||||
|
||||
# generic best-effort: fetch latest release archive matching host arch,
|
||||
# extract a single binary into /usr/local/bin. Warns and continues on failure.
|
||||
_gh_release_binary() {
|
||||
local repo="$1" binname="$2"
|
||||
command -v "$binname" >/dev/null 2>&1 && { ok "$binname already present"; return; }
|
||||
local api="https://api.github.com/repos/$repo/releases/latest"
|
||||
local archpat
|
||||
case "$ARCH" in
|
||||
amd64) archpat='(x86_64|amd64)' ;;
|
||||
arm64) archpat='(aarch64|arm64)' ;;
|
||||
*) archpat="$ARCH" ;;
|
||||
esac
|
||||
local url url_line
|
||||
url_line=$(curl -fsSL "$api" \
|
||||
| grep -oE '"browser_download_url":\s*"[^"]+"' \
|
||||
| sed -E 's/.*"([^"]+)"/\1/' \
|
||||
| grep -Ei "\\.(tar\\.gz|zip)$" \
|
||||
| grep -Ei "$archpat" \
|
||||
| grep -Ei 'linux|musl|gnu|unknown' \
|
||||
| grep -viE 'sig|sha|checksum|deb|rpm|apk|msi|darwin|windows' \
|
||||
| head -1)
|
||||
url="$url_line"
|
||||
if [[ -z "$url" ]]; then warn "could not resolve $binname release asset for $ARCH — skipped"; return; fi
|
||||
local tmp; tmp="$(mktemp -d)"
|
||||
if ! curl -fsSL "$url" -o "$tmp/asset"; then warn "download $binname failed"; rm -rf "$tmp"; return; fi
|
||||
case "$url" in
|
||||
*.tar.gz|*.tgz) tar -xzf "$tmp/asset" -C "$tmp" ;;
|
||||
*.zip) unzip -oq "$tmp/asset" -d "$tmp" ;;
|
||||
esac
|
||||
local found
|
||||
found=$(find "$tmp" -type f -name "$binname" -perm -u+x | head -1)
|
||||
[[ -z "$found" ]] && found=$(find "$tmp" -type f -name "$binname" | head -1)
|
||||
if [[ -n "$found" ]]; then
|
||||
sudo_ install -m 0755 "$found" "/usr/local/bin/$binname"
|
||||
ok "$binname installed from GitHub release"
|
||||
else
|
||||
warn "$binname binary not found in archive — skipped"
|
||||
fi
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
# fd/bat: apt ships fdfind/batcat on debian; create canonical symlinks in ~/.local/bin.
|
||||
_apt_aliases_fixup() {
|
||||
local bin="$HOME/.local/bin"; mkdir -p "$bin"
|
||||
if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then
|
||||
ln -sf "$(command -v fdfind)" "$bin/fd"
|
||||
fi
|
||||
if command -v batcat >/dev/null 2>&1 && ! command -v bat >/dev/null 2>&1; then
|
||||
ln -sf "$(command -v batcat)" "$bin/bat"
|
||||
fi
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user